]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 Nov 2015 16:58:48 +0000 (08:58 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 Nov 2015 16:58:48 +0000 (08:58 -0800)
Pull thermal management fixes from Zhang Rui:
 "Specifics:

 - several fixes and cleanups on Rockchip thermal drivers.

 - add the missing support of RK3368 SoCs in Rockchip driver.

 - small fixes on of-thermal, power_allocator, rcar driver, IMX, and
   QCOM drivers, and also compilation fixes, on thermal.h, when thermal
   is not selected"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
  imx: thermal: use CPU temperature grade info for thresholds
  thermal: fix thermal_zone_bind_cooling_device prototype
  Revert "thermal: qcom_spmi: allow compile test"
  thermal: rcar_thermal: remove redundant operation
  thermal: of-thermal: Reduce log level for message when can't fine thermal zone
  thermal: power_allocator: Use temperature reading from tz
  thermal: rockchip: Support the RK3368 SoCs in thermal driver
  thermal: rockchip: consistently use int for temperatures
  thermal: rockchip: Add the sort mode for adc value increment or decrement
  thermal: rockchip: improve the conversion function
  thermal: rockchip: trivial: fix typo in commit
  thermal: rockchip: better to compatible the driver for different SoCs
  dt-bindings: rockchip-thermal: Support the RK3368 SoCs compatible

1122 files changed:
Documentation/ABI/testing/sysfs-driver-st [new file with mode: 0644]
Documentation/IPMI.txt
Documentation/SubmittingPatches
Documentation/arm/keystone/Overview.txt
Documentation/block/null_blk.txt
Documentation/devicetree/bindings/input/touchscreen/tsc2005.txt
Documentation/devicetree/bindings/mips/img/xilfpga.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ufs/ufs-qcom.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
Documentation/dontdiff
Documentation/email-clients.txt
Documentation/filesystems/Makefile
Documentation/filesystems/configfs/Makefile [deleted file]
Documentation/filesystems/configfs/configfs.txt
Documentation/filesystems/configfs/configfs_example_explicit.c [deleted file]
Documentation/filesystems/overlayfs.txt
Documentation/i2c/busses/i2c-i801
Documentation/kernel-parameters.txt
Documentation/networking/can.txt
Documentation/nvdimm/nvdimm.txt
Documentation/scsi/st.txt
Documentation/target/tcm_mod_builder.py
MAINTAINERS
Makefile
arch/arc/configs/axs101_defconfig
arch/arc/configs/axs103_defconfig
arch/arc/configs/axs103_smp_defconfig
arch/arc/configs/nsim_hs_defconfig
arch/arc/configs/nsim_hs_smp_defconfig
arch/arc/configs/nsimosci_hs_defconfig
arch/arc/configs/nsimosci_hs_smp_defconfig
arch/arc/configs/vdk_hs38_defconfig
arch/arc/configs/vdk_hs38_smp_defconfig
arch/arc/include/asm/irqflags-arcv2.h
arch/arc/include/asm/irqflags-compact.h
arch/arc/include/asm/processor.h
arch/arc/kernel/ctx_sw.c
arch/arc/kernel/ctx_sw_asm.S
arch/arc/kernel/entry-arcv2.S
arch/arc/kernel/entry-compact.S
arch/arc/kernel/entry.S
arch/arc/kernel/process.c
arch/arc/kernel/unwind.c
arch/arc/lib/memcpy-archs.S
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arc/plat-sim/platform.c
arch/arm/boot/dts/animeo_ip.dts
arch/arm/boot/dts/at91-foxg20.dts
arch/arm/boot/dts/at91-kizbox.dts
arch/arm/boot/dts/at91-kizbox2.dts
arch/arm/boot/dts/at91-kizboxmini.dts
arch/arm/boot/dts/at91-qil_a9260.dts
arch/arm/boot/dts/at91-sama5d2_xplained.dts
arch/arm/boot/dts/at91-sama5d3_xplained.dts
arch/arm/boot/dts/at91-sama5d4_xplained.dts
arch/arm/boot/dts/at91-sama5d4ek.dts
arch/arm/boot/dts/at91rm9200ek.dts
arch/arm/boot/dts/at91sam9261ek.dts
arch/arm/boot/dts/at91sam9263ek.dts
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9rlek.dts
arch/arm/boot/dts/at91sam9x5cm.dtsi
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/k2l-netcp.dtsi
arch/arm/boot/dts/kirkwood-ts219.dtsi
arch/arm/boot/dts/rk3288-veyron-minnie.dts
arch/arm/boot/dts/rk3288.dtsi
arch/arm/boot/dts/sama5d35ek.dts
arch/arm/boot/dts/sama5d4.dtsi
arch/arm/boot/dts/usb_a9260_common.dtsi
arch/arm/boot/dts/usb_a9263.dts
arch/arm/boot/dts/vfxxx.dtsi
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/sama5_defconfig
arch/arm/include/asm/irq.h
arch/arm/kernel/bios32.c
arch/arm/kvm/arm.c
arch/arm/kvm/mmu.c
arch/arm/mach-dove/include/mach/entry-macro.S
arch/arm/mach-imx/gpc.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/omap_hwmod_81xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-orion5x/include/mach/entry-macro.S
arch/arm/mach-pxa/palm27x.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-shmobile/setup-r8a7793.c
arch/arm/mach-zx/Kconfig
arch/arm/net/bpf_jit_32.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/configs/defconfig
arch/arm64/crypto/aes-ce-cipher.c
arch/arm64/include/asm/atomic_ll_sc.h
arch/arm64/include/asm/atomic_lse.h
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/compat.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/dma-mapping.h
arch/arm64/include/asm/hw_breakpoint.h
arch/arm64/include/asm/irq.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/mmu_context.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/cpuinfo.c
arch/arm64/kernel/efi.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/suspend.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kvm/hyp.S
arch/arm64/kvm/inject_fault.c
arch/arm64/mm/context.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/fault.c
arch/arm64/mm/mmu.c
arch/arm64/net/bpf_jit.h
arch/arm64/net/bpf_jit_comp.c
arch/h8300/Kconfig
arch/h8300/Makefile
arch/h8300/boot/compressed/Makefile
arch/h8300/boot/compressed/head.S
arch/h8300/boot/compressed/misc.c
arch/h8300/boot/compressed/vmlinux.lds
arch/h8300/boot/dts/edosk2674.dts
arch/h8300/include/asm/io.h
arch/h8300/include/asm/thread_info.h
arch/h8300/kernel/setup.c
arch/h8300/kernel/vmlinux.lds.S
arch/mips/Kbuild
arch/mips/Kbuild.platforms
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/Makefile
arch/mips/ath79/setup.c
arch/mips/bcm47xx/setup.c
arch/mips/bcm47xx/sprom.c
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/cpu.c
arch/mips/bcm63xx/dev-pcmcia.c
arch/mips/bcm63xx/irq.c
arch/mips/bcm63xx/setup.c
arch/mips/bcm63xx/timer.c
arch/mips/bmips/setup.c
arch/mips/boot/dts/Makefile
arch/mips/boot/dts/brcm/bcm7346.dtsi
arch/mips/boot/dts/brcm/bcm7358.dtsi
arch/mips/boot/dts/brcm/bcm7360.dtsi
arch/mips/boot/dts/brcm/bcm7362.dtsi
arch/mips/boot/dts/brcm/bcm7425.dtsi
arch/mips/boot/dts/brcm/bcm97346dbsmb.dts
arch/mips/boot/dts/brcm/bcm97358svmb.dts
arch/mips/boot/dts/brcm/bcm97360svmb.dts
arch/mips/boot/dts/brcm/bcm97362svmb.dts
arch/mips/boot/dts/mti/malta.dts
arch/mips/boot/dts/qca/ar9132.dtsi
arch/mips/boot/dts/xilfpga/Makefile [new file with mode: 0644]
arch/mips/boot/dts/xilfpga/microAptiv.dtsi [new file with mode: 0644]
arch/mips/boot/dts/xilfpga/nexys4ddr.dts [new file with mode: 0644]
arch/mips/cavium-octeon/setup.c
arch/mips/configs/bigsur_defconfig
arch/mips/configs/bmips_be_defconfig
arch/mips/configs/bmips_stb_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/fuloong2e_defconfig
arch/mips/configs/lasat_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/malta_kvm_defconfig
arch/mips/configs/malta_kvm_guest_defconfig
arch/mips/configs/malta_qemu_32r6_defconfig
arch/mips/configs/maltaaprp_defconfig
arch/mips/configs/maltasmvp_eva_defconfig
arch/mips/configs/maltaup_defconfig
arch/mips/configs/maltaup_xpa_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/xilfpga_defconfig [new file with mode: 0644]
arch/mips/include/asm/abi.h
arch/mips/include/asm/atomic.h
arch/mips/include/asm/bcache.h
arch/mips/include/asm/cdmm.h
arch/mips/include/asm/clocksource.h [new file with mode: 0644]
arch/mips/include/asm/compat.h
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/debug.h [new file with mode: 0644]
arch/mips/include/asm/elf.h
arch/mips/include/asm/fw/fw.h
arch/mips/include/asm/mach-bcm47xx/bcm47xx.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
arch/mips/include/asm/mach-malta/malta-dtshim.h [new file with mode: 0644]
arch/mips/include/asm/mach-ralink/mt7620.h
arch/mips/include/asm/mach-ralink/ralink_regs.h
arch/mips/include/asm/mach-ralink/rt305x.h
arch/mips/include/asm/mach-xilfpga/irq.h [new file with mode: 0644]
arch/mips/include/asm/mips-cm.h
arch/mips/include/asm/mips-cpc.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/page.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/vdso.h
arch/mips/include/uapi/asm/Kbuild
arch/mips/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/mips/jz4740/board-qi_lb60.c
arch/mips/kernel/Makefile
arch/mips/kernel/cps-vec-ns16550.S [new file with mode: 0644]
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/csrc-r4k.c
arch/mips/kernel/idle.c
arch/mips/kernel/mips-cm.c
arch/mips/kernel/mips-cpc.c
arch/mips/kernel/mips-r2-to-r6-emul.c
arch/mips/kernel/segment.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp-gic.c
arch/mips/kernel/spinlock_test.c
arch/mips/kernel/stacktrace.c
arch/mips/kernel/traps.c
arch/mips/kernel/unaligned.c
arch/mips/kernel/vdso.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kvm/emulate.c
arch/mips/kvm/locore.S
arch/mips/kvm/mips.c
arch/mips/lantiq/clk.c
arch/mips/lantiq/clk.h
arch/mips/lantiq/irq.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/xway/clk.c
arch/mips/lantiq/xway/prom.c
arch/mips/lantiq/xway/reset.c
arch/mips/lantiq/xway/sysctrl.c
arch/mips/lib/Makefile
arch/mips/lib/bswapdi.c [new file with mode: 0644]
arch/mips/lib/bswapsi.c [new file with mode: 0644]
arch/mips/loongson64/Kconfig
arch/mips/loongson64/common/Makefile
arch/mips/loongson64/lemote-2f/Makefile
arch/mips/math-emu/me-debugfs.c
arch/mips/mm/Makefile
arch/mips/mm/sc-debugfs.c [new file with mode: 0644]
arch/mips/mm/sc-mips.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/Makefile
arch/mips/mti-malta/malta-dtshim.c [new file with mode: 0644]
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-memory.c
arch/mips/mti-malta/malta-setup.c
arch/mips/netlogic/xlp/dt.c
arch/mips/pci/pci-rt3883.c
arch/mips/pistachio/init.c
arch/mips/ralink/cevt-rt3352.c
arch/mips/ralink/early_printk.c
arch/mips/ralink/mt7620.c
arch/mips/ralink/of.c
arch/mips/ralink/prom.c
arch/mips/ralink/reset.c
arch/mips/ralink/rt288x.c
arch/mips/ralink/rt305x.c
arch/mips/ralink/rt3883.c
arch/mips/vdso/.gitignore [new file with mode: 0644]
arch/mips/vdso/Makefile [new file with mode: 0644]
arch/mips/vdso/elf.S [new file with mode: 0644]
arch/mips/vdso/genvdso.c [new file with mode: 0644]
arch/mips/vdso/genvdso.h [new file with mode: 0644]
arch/mips/vdso/gettimeofday.c [new file with mode: 0644]
arch/mips/vdso/sigreturn.S [new file with mode: 0644]
arch/mips/vdso/vdso.h [new file with mode: 0644]
arch/mips/vdso/vdso.lds.S [new file with mode: 0644]
arch/mips/xilfpga/Kconfig [new file with mode: 0644]
arch/mips/xilfpga/Makefile [new file with mode: 0644]
arch/mips/xilfpga/Platform [new file with mode: 0644]
arch/mips/xilfpga/init.c [new file with mode: 0644]
arch/mips/xilfpga/intc.c [new file with mode: 0644]
arch/mips/xilfpga/time.c [new file with mode: 0644]
arch/nios2/mm/cacheflush.c
arch/parisc/Kconfig
arch/parisc/include/asm/hugetlb.h [new file with mode: 0644]
arch/parisc/include/asm/page.h
arch/parisc/include/asm/pgalloc.h
arch/parisc/include/asm/pgtable.h
arch/parisc/include/asm/processor.h
arch/parisc/include/uapi/asm/mman.h
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/head.S
arch/parisc/kernel/setup.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/traps.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/Makefile
arch/parisc/mm/hugetlbpage.c [new file with mode: 0644]
arch/parisc/mm/init.c
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/process.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/s390/include/asm/cio.h
arch/s390/include/asm/elf.h
arch/s390/include/asm/ipl.h
arch/s390/include/asm/pci_dma.h
arch/s390/include/asm/trace/diag.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/diag.c
arch/s390/kernel/head.S
arch/s390/kernel/ipl.c
arch/s390/kernel/process.c
arch/s390/kernel/sclp.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/trace.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/mm/init.c
arch/s390/mm/mmap.c
arch/s390/pci/pci_dma.c
arch/x86/include/asm/i8259.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/vmx.h
arch/x86/include/uapi/asm/svm.h
arch/x86/kernel/apic/vector.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/perf_event_intel_rapl.c
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/head_64.S
arch/x86/kernel/i8259.c
arch/x86/kernel/mcount_64.S
arch/x86/kernel/setup.c
arch/x86/kernel/verify_cpu.S
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/dump_pagetables.c
arch/x86/mm/mpx.c
block/blk-core.c
block/blk-merge.c
block/blk-mq.c
block/blk-mq.h
block/blk-timeout.c
block/blk.h
block/noop-iosched.c
block/partitions/mac.c
crypto/asymmetric_keys/x509_cert_parser.c
drivers/Makefile
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_video.c
drivers/acpi/cppc_acpi.c
drivers/acpi/ec.c
drivers/acpi/glue.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/video_detect.c
drivers/ata/libata-scsi.c
drivers/base/power/domain.c
drivers/base/power/opp/core.c
drivers/base/power/opp/cpu.c
drivers/base/power/opp/opp.h
drivers/base/power/wakeirq.c
drivers/base/property.c
drivers/block/brd.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/null_blk.c
drivers/block/rbd.c
drivers/bus/omap-ocp2scp.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_of.c
drivers/char/tpm/tpm_tis.c
drivers/clk/h8300/clk-div.c
drivers/clocksource/Kconfig
drivers/clocksource/fsl_ftm_timer.c
drivers/clocksource/mips-gic-timer.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/cppc_cpufreq.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/s5pv210-cpufreq.c
drivers/crypto/ccp/ccp-platform.c
drivers/crypto/qat/qat_common/adf_ctl_drv.c
drivers/dma/at_hdmac.c
drivers/dma/at_hdmac_regs.h
drivers/dma/at_xdmac.c
drivers/dma/edma.c
drivers/dma/imx-sdma.c
drivers/dma/sh/usb-dmac.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
drivers/gpu/drm/amd/amdgpu/amdgpu_semaphore.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
drivers/gpu/drm/amd/scheduler/sched_fence.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mgag200/mgag200_cursor.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/sti/Kconfig
drivers/gpu/drm/sti/Makefile
drivers/gpu/drm/sti/sti_awg_utils.c
drivers/gpu/drm/sti/sti_compositor.c
drivers/gpu/drm/sti/sti_crtc.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sti/sti_drv.h
drivers/gpu/drm/sti/sti_dvo.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_hda.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_hqvdp.c
drivers/gpu/drm/sti/sti_mixer.c
drivers/gpu/drm/sti/sti_plane.c
drivers/gpu/drm/sti/sti_tvout.c
drivers/gpu/drm/sti/sti_vtac.c
drivers/gpu/drm/sti/sti_vtg.c
drivers/gpu/drm/sti/sti_vtg.h
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/hid/wacom_wac.c
drivers/hwmon/Kconfig
drivers/hwmon/applesmc.c
drivers/hwmon/scpi-hwmon.c
drivers/hwtracing/stm/policy.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/i2c-core.c
drivers/iio/adc/ad7793.c
drivers/iio/adc/vf610_adc.c
drivers/iio/adc/xilinx-xadc-core.c
drivers/iio/dac/ad5064.c
drivers/iio/humidity/si7020.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/mouse/elantech.c
drivers/input/serio/parkbd.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/tsc2004.c [new file with mode: 0644]
drivers/input/touchscreen/tsc2005.c
drivers/input/touchscreen/tsc200x-core.c [new file with mode: 0644]
drivers/input/touchscreen/tsc200x-core.h [new file with mode: 0644]
drivers/iommu/s390-iommu.c
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-mips-gic.c
drivers/lightnvm/core.c
drivers/lightnvm/gennvm.c
drivers/lightnvm/gennvm.h
drivers/lightnvm/rrpc.c
drivers/md/dm-crypt.c
drivers/md/dm-mpath.c
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx25821/cx25821-core.c
drivers/media/pci/cx88/cx88-alsa.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/netup_unidvb/netup_unidvb_core.c
drivers/media/pci/saa7134/saa7134-core.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/pci/tw68/tw68-core.c
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptsas.c
drivers/misc/spear13xx_pcie_gadget.c
drivers/mmc/card/block.c
drivers/mmc/core/mmc.c
drivers/mmc/host/Kconfig
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/pxamci.c
drivers/mtd/nand/jz4740_nand.c
drivers/mtd/nand/nand_base.c
drivers/net/dsa/mv88e6060.c
drivers/net/dsa/mv88e6060.h [new file with mode: 0644]
drivers/net/ethernet/Kconfig
drivers/net/ethernet/Makefile
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/amd/xgbe/xgbe-main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/cavium/liquidio/lio_main.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/dlink/Kconfig
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/dl2k.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/icplus/Kconfig [deleted file]
drivers/net/ethernet/icplus/Makefile [deleted file]
drivers/net/ethernet/icplus/ipg.c [deleted file]
drivers/net/ethernet/icplus/ipg.h [deleted file]
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/fjes/fjes_hw.c
drivers/net/ipvlan/ipvlan_core.c
drivers/net/macvlan.c
drivers/net/netconsole.c
drivers/net/phy/at803x.c
drivers/net/phy/marvell.c
drivers/net/phy/phy.c
drivers/net/phy/vitesse.c
drivers/net/usb/cdc_ether.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/nvdimm/e820.c
drivers/nvdimm/pmem.c
drivers/nvme/host/lightnvm.c
drivers/nvme/host/pci.c
drivers/of/of_pci.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-hisi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/platform/chrome/Kconfig
drivers/platform/chrome/Makefile
drivers/platform/chrome/chromeos_laptop.c
drivers/platform/chrome/cros_ec_dev.c
drivers/platform/chrome/cros_ec_lightbar.c
drivers/platform/chrome/cros_ec_lpc.c
drivers/platform/chrome/cros_ec_vbc.c [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/cio.c
drivers/s390/cio/css.c
drivers/s390/crypto/Makefile
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/scsi/53c700.c
drivers/scsi/FlashPoint.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/rx.c
drivers/scsi/aacraid/sa.c
drivers/scsi/aacraid/src.c
drivers/scsi/advansys.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
drivers/scsi/bnx2fc/Kconfig
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_constants.h
drivers/scsi/bnx2fc/bnx2fc_debug.c
drivers/scsi/bnx2fc/bnx2fc_debug.h
drivers/scsi/bnx2fc/bnx2fc_els.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c
drivers/scsi/csiostor/csio_scsi.c
drivers/scsi/esas2r/esas2r_main.c
drivers/scsi/esp_scsi.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/hpsa_cmd.h
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ibmvscsi/ibmvscsi.h
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/isci/init.c
drivers/scsi/libfc/fc_npiv.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/megaraid/megaraid_sas_fusion.h
drivers/scsi/mpt2sas/Kconfig [deleted file]
drivers/scsi/mpt2sas/Makefile [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_init.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_ioc.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_raid.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_sas.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_tool.h [deleted file]
drivers/scsi/mpt2sas/mpi/mpi2_type.h [deleted file]
drivers/scsi/mpt2sas/mpt2sas_base.c [deleted file]
drivers/scsi/mpt2sas/mpt2sas_base.h [deleted file]
drivers/scsi/mpt2sas/mpt2sas_config.c [deleted file]
drivers/scsi/mpt2sas/mpt2sas_ctl.c [deleted file]
drivers/scsi/mpt2sas/mpt2sas_ctl.h [deleted file]
drivers/scsi/mpt2sas/mpt2sas_debug.h [deleted file]
drivers/scsi/mpt2sas/mpt2sas_scsih.c [deleted file]
drivers/scsi/mpt2sas/mpt2sas_transport.c [deleted file]
drivers/scsi/mpt3sas/Kconfig
drivers/scsi/mpt3sas/Makefile
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/mpt3sas/mpt3sas_config.c
drivers/scsi/mpt3sas/mpt3sas_ctl.c
drivers/scsi/mpt3sas/mpt3sas_ctl.h
drivers/scsi/mpt3sas/mpt3sas_debug.h
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/mpt3sas/mpt3sas_transport.c
drivers/scsi/mpt3sas/mpt3sas_warpdrive.c [new file with mode: 0644]
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvumi.c
drivers/scsi/pm8001/pm8001_defs.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/pmcraid.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/snic/snic_main.c
drivers/scsi/st.c
drivers/scsi/stex.c
drivers/scsi/storvsc_drv.c
drivers/scsi/ufs/Kconfig
drivers/scsi/ufs/ufs-qcom.c
drivers/scsi/ufs/ufs-qcom.h
drivers/scsi/ufs/ufshcd-pltfrm.c
drivers/scsi/ufs/ufshcd-pltfrm.h [new file with mode: 0644]
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/sh/pm_runtime.c
drivers/soc/mediatek/Kconfig
drivers/soc/ti/knav_qmss_queue.c
drivers/staging/iio/Kconfig
drivers/staging/iio/adc/lpc32xx_adc.c
drivers/staging/wilc1000/coreconfigurator.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_stat.c
drivers/target/loopback/tcm_loop.c
drivers/target/sbp/sbp_target.c
drivers/target/target_core_configfs.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_internal.h
drivers/target/target_core_stat.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_conf.c
drivers/target/tcm_fc/tfc_io.c
drivers/target/tcm_fc/tfc_sess.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_fsl.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/Kconfig
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/etraxfs-uart.c
drivers/tty/tty_audit.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/tty_ldisc.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/class/usblp.c
drivers/usb/core/Kconfig
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_acm.c
drivers/usb/gadget/function/f_ecm.c
drivers/usb/gadget/function/f_eem.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_midi.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/f_obex.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/f_printer.c
drivers/usb/gadget/function/f_rndis.c
drivers/usb/gadget/function/f_serial.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/function/f_subset.c
drivers/usb/gadget/function/f_uac1.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/u_ether_configfs.h
drivers/usb/gadget/function/uvc_configfs.c
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_host.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-omap-otg.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/ti_usb_3410_5052.h
drivers/usb/storage/uas.c
drivers/vfio/Kconfig
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_config.c
drivers/vfio/platform/Makefile
drivers/vfio/platform/reset/Kconfig
drivers/vfio/platform/reset/Makefile
drivers/vfio/platform/reset/vfio_platform_amdxgbe.c [new file with mode: 0644]
drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c
drivers/vfio/platform/vfio_amba.c
drivers/vfio/platform/vfio_platform.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/platform/vfio_platform_irq.c
drivers/vfio/platform/vfio_platform_private.h
drivers/vfio/vfio.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/scsi.c
drivers/watchdog/Kconfig
drivers/watchdog/mtk_wdt.c
drivers/watchdog/omap_wdt.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/tegra_wdt.c
drivers/watchdog/w83977f_wdt.c
drivers/xen/events/events_base.c
drivers/xen/evtchn.c
drivers/xen/gntdev.c
drivers/xen/xen-scsiback.c
fs/9p/Makefile
fs/9p/acl.c
fs/9p/xattr.c
fs/9p/xattr.h
fs/9p/xattr_security.c [deleted file]
fs/9p/xattr_trusted.c [deleted file]
fs/9p/xattr_user.c [deleted file]
fs/Kconfig
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/qgroup.c
fs/btrfs/scrub.c
fs/btrfs/tests/free-space-tests.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/btrfs/xattr.c
fs/cachefiles/rdwr.c
fs/ceph/cache.c
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/ioctl.c
fs/cifs/smb2file.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smbfsctl.h
fs/configfs/dir.c
fs/configfs/file.c
fs/dax.c
fs/dlm/config.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/ext2/xattr_security.c
fs/ext2/xattr_trusted.c
fs/ext2/xattr_user.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/ext4/xattr_security.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/f2fs/xattr.c
fs/fat/dir.c
fs/gfs2/xattr.c
fs/hfsplus/xattr.c
fs/hfsplus/xattr_security.c
fs/hfsplus/xattr_trusted.c
fs/hfsplus/xattr_user.c
fs/hugetlbfs/inode.c
fs/jffs2/security.c
fs/jffs2/xattr.c
fs/jffs2/xattr_trusted.c
fs/jffs2/xattr_user.c
fs/ncpfs/ioctl.c
fs/nfs/callback_xdr.c
fs/nfs/inode.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/nodemanager.c
fs/ocfs2/namei.c
fs/ocfs2/xattr.c
fs/posix_acl.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr_security.c
fs/reiserfs/xattr_trusted.c
fs/reiserfs/xattr_user.c
fs/splice.c
fs/squashfs/xattr.c
fs/sysfs/group.c
fs/sysv/inode.c
fs/ubifs/super.c
fs/ubifs/ubifs.h
fs/ubifs/xattr.c
fs/xattr.c
fs/xfs/xfs_xattr.c
include/acpi/acpi_bus.h
include/asm-generic/uaccess.h
include/drm/drm_atomic.h
include/kvm/arm_vgic.h
include/linux/acpi.h
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/ceph/libceph.h
include/linux/ceph/messenger.h
include/linux/configfs.h
include/linux/context_tracking.h
include/linux/gfp.h
include/linux/irqchip/mips-gic.h
include/linux/kvm_host.h
include/linux/lightnvm.h
include/linux/marvell_phy.h
include/linux/math64.h
include/linux/mfd/cros_ec.h
include/linux/mlx5/mlx5_ifc.h
include/linux/netdevice.h
include/linux/netfilter/ipset/ip_set.h
include/linux/netfilter_ingress.h
include/linux/nfs_xdr.h
include/linux/of_dma.h
include/linux/of_pci.h
include/linux/pci.h
include/linux/property.h
include/linux/scpi_protocol.h
include/linux/signal.h
include/linux/slab.h
include/linux/syscalls.h
include/linux/sysfs.h
include/linux/tty.h
include/linux/types.h
include/linux/usb/gadget_configfs.h
include/linux/vfio.h
include/linux/xattr.h
include/net/ip6_fib.h
include/net/ip6_tunnel.h
include/net/ip_tunnels.h
include/net/netfilter/nf_tables.h
include/net/sock.h
include/net/switchdev.h
include/scsi/scsi_host.h
include/scsi/scsi_tcq.h
include/target/configfs_macros.h [deleted file]
include/target/target_core_base.h
include/target/target_core_fabric_configfs.h [deleted file]
include/uapi/drm/drm_fourcc.h
include/uapi/linux/nfs.h
include/uapi/linux/vfio.h
kernel/context_tracking.c
kernel/events/core.c
kernel/irq/internals.h
kernel/irq/pm.c
kernel/irq/proc.c
kernel/livepatch/core.c
kernel/panic.c
kernel/pid.c
kernel/sched/fair.c
kernel/signal.c
kernel/time/timer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
mm/huge_memory.c
mm/kasan/kasan.c
mm/memory.c
mm/page-writeback.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slob.c
mm/slub.c
mm/vmalloc.c
net/8021q/vlan_core.c
net/bridge/br_stp.c
net/bridge/br_stp_if.c
net/ceph/auth_x.c
net/ceph/ceph_common.c
net/ceph/crypto.h
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/neighbour.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/inet_connection_sock.c
net/ipv4/netfilter/nf_nat_pptp.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/tcp_diag.c
net/ipv4/tcp_ipv4.c
net/ipv6/mcast.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/netfilter/Kconfig
net/netfilter/ipset/ip_set_bitmap_gen.h
net/netfilter/ipset/ip_set_bitmap_ip.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_bitmap_port.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/ipset/ip_set_list_set.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/nfnetlink_log.c
net/netfilter/nft_counter.c
net/netfilter/nft_dynset.c
net/packet/af_packet.c
net/sctp/auth.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/svc.c
net/unix/af_unix.c
samples/Kconfig
samples/Makefile
samples/bpf/Makefile
samples/configfs/Makefile [new file with mode: 0644]
samples/configfs/configfs_sample.c [moved from Documentation/filesystems/configfs/configfs_example_macros.c with 74% similarity]
scripts/kernel-doc
security/keys/encrypted-keys/encrypted.c
security/keys/trusted.c
security/keys/user_defined.c
security/selinux/ss/conditional.c
sound/firewire/Kconfig
sound/firewire/dice/dice.c
sound/pci/Kconfig
sound/pci/ctxfi/ctamixer.c
sound/pci/ctxfi/ctamixer.h
sound/pci/ctxfi/ctdaio.c
sound/pci/ctxfi/ctdaio.h
sound/pci/ctxfi/ctresource.c
sound/pci/ctxfi/ctresource.h
sound/pci/ctxfi/ctsrc.c
sound/pci/ctxfi/ctsrc.h
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_jack.h
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/sound_core.c
sound/usb/midi.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/usbaudio.h
tools/Makefile
tools/include/linux/list.h
tools/lib/bpf/.gitignore
tools/lib/bpf/Makefile
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/lockdep/common.c
tools/lib/lockdep/include/liblockdep/common.h
tools/lib/lockdep/uinclude/linux/compiler.h
tools/lib/lockdep/uinclude/linux/lockdep.h
tools/net/Makefile
tools/perf/Documentation/perf-trace.txt
tools/perf/Makefile
tools/perf/builtin-inject.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-stat.c
tools/perf/tests/.gitignore [new file with mode: 0644]
tools/perf/tests/Build
tools/perf/tests/attr.c
tools/perf/tests/bpf-script-example.c
tools/perf/tests/bpf-script-test-kbuild.c [new file with mode: 0644]
tools/perf/tests/bpf.c [new file with mode: 0644]
tools/perf/tests/builtin-test.c
tools/perf/tests/code-reading.c
tools/perf/tests/keep-tracking.c
tools/perf/tests/llvm.c
tools/perf/tests/llvm.h [new file with mode: 0644]
tools/perf/tests/make
tools/perf/tests/switch-tracking.c
tools/perf/tests/tests.h
tools/perf/ui/browsers/hists.c
tools/perf/util/annotate.c
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/build-id.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/llvm-utils.c
tools/perf/util/machine.c
tools/perf/util/map.c
tools/perf/util/parse-events.c
tools/perf/util/probe-event.c
tools/perf/util/probe-file.c
tools/perf/util/probe-finder.c
tools/perf/util/session.c
tools/perf/util/stat-shadow.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/util.c
tools/perf/util/util.h
tools/power/cpupower/debug/i386/dump_psb.c
tools/power/cpupower/man/cpupower-idle-set.1
tools/power/cpupower/utils/cpufreq-info.c
tools/power/cpupower/utils/cpufreq-set.c
tools/power/cpupower/utils/cpuidle-info.c
tools/power/cpupower/utils/cpuidle-set.c
tools/power/cpupower/utils/cpupower-info.c
tools/power/cpupower/utils/cpupower-set.c
tools/power/cpupower/utils/helpers/topology.c
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
tools/power/x86/turbostat/turbostat.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/futex/README
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/vm/page-types.c
virt/kvm/arm/arch_timer.c
virt/kvm/arm/vgic.c

diff --git a/Documentation/ABI/testing/sysfs-driver-st b/Documentation/ABI/testing/sysfs-driver-st
new file mode 100644 (file)
index 0000000..ba5d770
--- /dev/null
@@ -0,0 +1,12 @@
+What:          /sys/bus/scsi/drivers/st/debug_flag
+Date:          October 2015
+Kernel Version:        ?.?
+Contact:       shane.seymour@hpe.com
+Description:
+               This file allows you to turn debug output from the st driver
+               off if you write a '0' to the file or on if you write a '1'.
+               Note that debug output requires that the module be compiled
+               with the #define DEBUG set to a non-zero value (this is the
+               default). If DEBUG is set to 0 then this file will not
+               appear in sysfs as its presence is conditional upon debug
+               output support being compiled into the module.
index 31d1d658827f082f66c88c3147e99be3321635cf..c0d8788e75d3f1f2a335a27a883f161ad51128ac 100644 (file)
@@ -587,7 +587,7 @@ used to control it:
 
   modprobe ipmi_watchdog timeout=<t> pretimeout=<t> action=<action type>
       preaction=<preaction type> preop=<preop type> start_now=x
-      nowayout=x ifnum_to_use=n
+      nowayout=x ifnum_to_use=n panic_wdt_timeout=<t>
 
 ifnum_to_use specifies which interface the watchdog timer should use.
 The default is -1, which means to pick the first one registered.
@@ -597,7 +597,9 @@ is the amount of seconds before the reset that the pre-timeout panic will
 occur (if pretimeout is zero, then pretimeout will not be enabled).  Note
 that the pretimeout is the time before the final timeout.  So if the
 timeout is 50 seconds and the pretimeout is 10 seconds, then the pretimeout
-will occur in 40 second (10 seconds before the timeout).
+will occur in 40 second (10 seconds before the timeout). The panic_wdt_timeout
+is the value of timeout which is set on kernel panic, in order to let actions
+such as kdump to occur during panic.
 
 The action may be "reset", "power_cycle", or "power_off", and
 specifies what to do when the timer times out, and defaults to
@@ -634,6 +636,7 @@ for configuring the watchdog:
        ipmi_watchdog.preop=<preop type>
        ipmi_watchdog.start_now=x
        ipmi_watchdog.nowayout=x
+       ipmi_watchdog.panic_wdt_timeout=<t>
 
 The options are the same as the module parameter options.
 
index 4710e4afef19c40b146e50c9fedff8b9fc308ead..d603fa07823598b87dc48d0e8362a6fcb5a57a32 100644 (file)
@@ -718,8 +718,21 @@ generates appropriate diffstats by default.)
 See more details on the proper patch format in the following
 references.
 
+15) Explicit In-Reply-To headers
+--------------------------------
+
+It can be helpful to manually add In-Reply-To: headers to a patch
+(e.g., when using "git send email") to associate the patch with
+previous relevant discussion, e.g. to link a bug fix to the email with
+the bug report.  However, for a multi-patch series, it is generally
+best to avoid using In-Reply-To: to link to older versions of the
+series.  This way multiple versions of the patch don't become an
+unmanageable forest of references in email clients.  If a link is
+helpful, you can use the https://lkml.kernel.org/ redirector (e.g., in
+the cover email text) to link to an earlier version of the patch series.
+
 
-15) Sending "git pull" requests
+16) Sending "git pull" requests
 -------------------------------
 
 If you have a series of patches, it may be most convenient to have the
index f17bc4c9dff9fa1334d518e0a6c0ffc8ac270e3a..400c0c270d2e8d935e55fc1396989e75abbad36d 100644 (file)
@@ -49,24 +49,6 @@ specified through DTS. Following are the DTS used:-
 The device tree documentation for the keystone machines are located at
         Documentation/devicetree/bindings/arm/keystone/keystone.txt
 
-Known issues & workaround
--------------------------
-
-Some of the device drivers used on keystone are re-used from that from
-DaVinci and other TI SoCs. These device drivers may use clock APIs directly.
-Some of the keystone specific drivers such as netcp uses run time power
-management API instead to enable clock. As this API has limitations on
-keystone, following workaround is needed to boot Linux.
-
-   Add 'clk_ignore_unused' to the bootargs env variable in u-boot. Otherwise
-   clock frameworks will try to disable clocks that are unused and disable
-   the hardware. This is because netcp related power domain and clock
-   domains are enabled in u-boot as run time power management API currently
-   doesn't enable clocks for netcp due to a limitation. This workaround is
-   expected to be removed in the future when proper API support becomes
-   available. Until then, this work around is needed.
-
-
 Document Author
 ---------------
 Murali Karicheri <m-karicheri2@ti.com>
index 2f6c6ff7161d4e77f3ec8ffee998b19f53b18cf7..d8880ca30af4c35d562c0f77b1b3a56c3ff6e1d7 100644 (file)
@@ -70,3 +70,6 @@ use_per_node_hctx=[0/1]: Default: 0
      parameter.
   1: The multi-queue block layer is instantiated with a hardware dispatch
      queue for each CPU node in the system.
+
+use_lightnvm=[0/1]: Default: 0
+  Register device with LightNVM. Requires blk-mq to be used.
index 09089a6d69ed8d1c9b29115e6abce75a6d1a2fcd..b80c04b0e5c028a45ae85f3ba77230b509318037 100644 (file)
@@ -1,14 +1,15 @@
-* Texas Instruments tsc2005 touchscreen controller
+* Texas Instruments tsc2004 and tsc2005 touchscreen controllers
 
 Required properties:
- - compatible                : "ti,tsc2005"
- - reg                       : SPI device address
- - spi-max-frequency         : Maximal SPI speed
+ - compatible                : "ti,tsc2004" or "ti,tsc2005"
+ - reg                       : Device address
  - interrupts                : IRQ specifier
- - reset-gpios               : GPIO specifier
- - vio-supply                 : Regulator specifier
+ - spi-max-frequency         : Maximum SPI clocking speed of the device
+                               (for tsc2005)
 
 Optional properties:
+ - vio-supply                : Regulator specifier
+ - reset-gpios               : GPIO specifier for the controller reset line
  - ti,x-plate-ohms           : integer, resistance of the touchscreen's X plates
                                in ohm (defaults to 280)
  - ti,esd-recovery-timeout-ms : integer, if the touchscreen does not respond after
@@ -18,6 +19,27 @@ Optional properties:
 
 Example:
 
+&i2c3 {
+       tsc2004@48 {
+               compatible = "ti,tsc2004";
+               reg = <0x48>;
+               vio-supply = <&vio>;
+
+               reset-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+               interrupts-extended = <&gpio1 27 IRQ_TYPE_EDGE_RISING>;
+
+               touchscreen-fuzz-x = <4>;
+               touchscreen-fuzz-y = <7>;
+               touchscreen-fuzz-pressure = <2>;
+               touchscreen-size-x = <4096>;
+               touchscreen-size-y = <4096>;
+               touchscreen-max-pressure = <2048>;
+
+               ti,x-plate-ohms = <280>;
+               ti,esd-recovery-timeout-ms = <8000>;
+       };
+}
+
 &mcspi1 {
        tsc2005@0 {
                compatible = "ti,tsc2005";
diff --git a/Documentation/devicetree/bindings/mips/img/xilfpga.txt b/Documentation/devicetree/bindings/mips/img/xilfpga.txt
new file mode 100644 (file)
index 0000000..57e7ee9
--- /dev/null
@@ -0,0 +1,83 @@
+Imagination University Program MIPSfpga
+=======================================
+
+Under the Imagination University Program, a microAptiv UP core has been
+released for academic usage.
+
+As we are dealing with a MIPS core instantiated on an FPGA, specifications
+are fluid and can be varied in RTL.
+
+This binding document is provided as baseline guidance for the example
+project provided by IMG.
+
+The example project runs on the Nexys4DDR board by Digilent powered by
+the ARTIX-7 FPGA by Xilinx.
+
+Relevant details about the example project and the Nexys4DDR board:
+
+- microAptiv UP core m14Kc
+- 50MHz clock speed
+- 128Mbyte DDR RAM     at 0x0000_0000
+- 8Kbyte RAM           at 0x1000_0000
+- axi_intc             at 0x1020_0000
+- axi_uart16550                at 0x1040_0000
+- axi_gpio             at 0x1060_0000
+- axi_i2c              at 0x10A0_0000
+- custom_gpio          at 0x10C0_0000
+- axi_ethernetlite     at 0x10E0_0000
+- 8Kbyte BootRAM       at 0x1FC0_0000
+
+Required properties:
+--------------------
+ - compatible: Must include "digilent,nexys4ddr","img,xilfpga".
+
+CPU nodes:
+----------
+A "cpus" node is required.  Required properties:
+ - #address-cells: Must be 1.
+ - #size-cells: Must be 0.
+A CPU sub-node is also required for at least CPU 0. Required properties:
+ - device_type: Must be "cpu".
+ - compatible: Must be "mips,m14Kc".
+ - reg: Must be <0>.
+ - clocks: phandle to ext clock for fixed-clock received by MIPS core.
+
+Example:
+
+       compatible = "img,xilfpga","digilent,nexys4ddr";
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,m14Kc";
+                       reg = <0>;
+                       clocks  = <&ext>;
+               };
+       };
+
+       ext: ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
+       };
+
+Boot protocol:
+--------------
+
+The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000.
+This is for easy reprogrammibility via JTAG.
+
+The BootRAM initializes the cache and the axi_uart peripheral.
+
+DDR initialization is already handled by a HW IP block.
+
+When the example project bitstream is loaded, the cpu_reset button
+needs to be pressed.
+
+The bootram initializes the cache and axi_uart.
+Then outputs MIPSFPGA\n\r on the serial port on the Nexys4DDR board.
+
+At this point, the board is ready to load the Linux kernel
+vmlinux file via JTAG.
diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
new file mode 100644 (file)
index 0000000..070baf4
--- /dev/null
@@ -0,0 +1,58 @@
+* Qualcomm Technologies Inc Universal Flash Storage (UFS) PHY
+
+UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro.
+Each UFS PHY node should have its own node.
+
+To bind UFS PHY with UFS host controller, the controller node should
+contain a phandle reference to UFS PHY node.
+
+Required properties:
+- compatible        : compatible list, contains "qcom,ufs-phy-qmp-20nm"
+                     or "qcom,ufs-phy-qmp-14nm" according to the relevant phy in use.
+- reg               : should contain PHY register address space (mandatory),
+- reg-names         : indicates various resources passed to driver (via reg proptery) by name.
+                      Required "reg-names" is "phy_mem".
+- #phy-cells        : This property shall be set to 0
+- vdda-phy-supply   : phandle to main PHY supply for analog domain
+- vdda-pll-supply   : phandle to PHY PLL and Power-Gen block power supply
+- clocks           : List of phandle and clock specifier pairs
+- clock-names       : List of clock input name strings sorted in the same
+                     order as the clocks property. "ref_clk_src", "ref_clk",
+                     "tx_iface_clk" & "rx_iface_clk" are mandatory but
+                     "ref_clk_parent" is optional
+
+Optional properties:
+- vdda-phy-max-microamp : specifies max. load that can be drawn from phy supply
+- vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply
+- vddp-ref-clk-supply   : phandle to UFS device ref_clk pad power supply
+- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply
+- vddp-ref-clk-always-on : specifies if this supply needs to be kept always on
+
+Example:
+
+       ufsphy1: ufsphy@0xfc597000 {
+               compatible = "qcom,ufs-phy-qmp-20nm";
+               reg = <0xfc597000 0x800>;
+               reg-names = "phy_mem";
+               #phy-cells = <0>;
+               vdda-phy-supply = <&pma8084_l4>;
+               vdda-pll-supply = <&pma8084_l12>;
+               vdda-phy-max-microamp = <50000>;
+               vdda-pll-max-microamp = <1000>;
+               clock-names = "ref_clk_src",
+                       "ref_clk_parent",
+                       "ref_clk",
+                       "tx_iface_clk",
+                       "rx_iface_clk";
+               clocks = <&clock_rpm clk_ln_bb_clk>,
+                       <&clock_gcc clk_pcie_1_phy_ldo >,
+                       <&clock_gcc clk_ufs_phy_ldo>,
+                       <&clock_gcc clk_gcc_ufs_tx_cfg_clk>,
+                       <&clock_gcc clk_gcc_ufs_rx_cfg_clk>;
+       };
+
+       ufshc@0xfc598000 {
+               ...
+               phys = <&ufsphy1>;
+               phy-names = "ufsphy";
+       };
index 53579197eca2a86b1b43e0cdf0ac9ba329831693..03c0e989e020a98ec28195896c8f8612686a580e 100644 (file)
@@ -4,11 +4,18 @@ UFSHC nodes are defined to describe on-chip UFS host controllers.
 Each UFS controller instance should have its own node.
 
 Required properties:
-- compatible        : compatible list, contains "jedec,ufs-1.1"
+- compatible           : must contain "jedec,ufs-1.1", may also list one or more
+                                         of the following:
+                                         "qcom,msm8994-ufshc"
+                                         "qcom,msm8996-ufshc"
+                                         "qcom,ufshc"
 - interrupts        : <interrupt mapping for UFS host controller IRQ>
 - reg               : <registers mapping>
 
 Optional properties:
+- phys                  : phandle to UFS PHY node
+- phy-names             : the string "ufsphy" when is found in a node, along
+                          with "phys" attribute, provides phandle to UFS PHY node
 - vdd-hba-supply        : phandle to UFS host controller supply regulator node
 - vcc-supply            : phandle to VCC supply regulator node
 - vccq-supply           : phandle to VCCQ supply regulator node
@@ -54,4 +61,6 @@ Example:
                clocks = <&core 0>, <&ref 0>, <&iface 0>;
                clock-names = "core_clk", "ref_clk", "iface_clk";
                freq-table-hz = <100000000 200000000>, <0 0>, <0 0>;
+               phys = <&ufsphy1>;
+               phy-names = "ufsphy";
        };
index 9de9813d0ec5df101a48428d40cfc9b9d2df6142..8ea834f6b2892a6ed7cccbc399cc5f1f3e887bd0 100644 (file)
@@ -165,7 +165,6 @@ mach-types.h
 machtypes.h
 map
 map_hugetlb
-media
 mconf
 miboot*
 mk_elfconfig
index aba85b39a40096872bc67b4e0303a381ec74693d..2d485dea8cece79d7a2db645a3011a27c76c47b4 100644 (file)
@@ -176,11 +176,47 @@ To use 'vim' with mutt:
 if you want to include the patch inline.
 (a)ttach works fine without "set paste".
 
+You can also generate patches with 'git format-patch' and then use Mutt
+to send them:
+    $ mutt -H 0001-some-bug-fix.patch
+
 Config options:
 It should work with default settings.
 However, it's a good idea to set the "send_charset" to:
   set send_charset="us-ascii:utf-8"
 
+Mutt is highly customizable. Here is a minimum configuration to start
+using Mutt to send patches through Gmail:
+
+# .muttrc
+# ================  IMAP ====================
+set imap_user = 'yourusername@gmail.com'
+set imap_pass = 'yourpassword'
+set spoolfile = imaps://imap.gmail.com/INBOX
+set folder = imaps://imap.gmail.com/
+set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+# ================  SMTP  ====================
+set smtp_url = "smtp://username@smtp.gmail.com:587/"
+set smtp_pass = $imap_pass
+set ssl_force_tls = yes # Require encrypted connection
+
+# ================  Composition  ====================
+set editor = `echo \$EDITOR`
+set edit_headers = yes  # See the headers when editing
+set charset = UTF-8     # value of $LANG; also fallback for send_charset
+# Sender, email address, and sign-off line must match
+unset use_domain        # because joe@localhost is just embarrassing
+set realname = "YOUR NAME"
+set from = "username@gmail.com"
+set use_from = yes
+
+The Mutt docs have lots more information:
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+    http://dev.mutt.org/doc/manual.html
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Pine (TUI)
 
index 13483d192ebb9f80bf541eead154f28c1eb44c0f..883010ce5e35bcd88885b0a5eeff68e82676029f 100644 (file)
@@ -1,5 +1,3 @@
-subdir-y := configfs
-
 # List of programs to build
 hostprogs-y := dnotify_test
 
diff --git a/Documentation/filesystems/configfs/Makefile b/Documentation/filesystems/configfs/Makefile
deleted file mode 100644 (file)
index be7ec5e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ifneq ($(CONFIG_CONFIGFS_FS),)
-obj-m += configfs_example_explicit.o configfs_example_macros.o
-endif
index b40fec9d3f53b6402a4a21ba74f170c466d73300..af68efdbbfaddb0827b29f1fc4fb4b0eacc43b3a 100644 (file)
@@ -160,12 +160,6 @@ among other things.  For that, it needs a type.
 
        struct configfs_item_operations {
                void (*release)(struct config_item *);
-               ssize_t (*show_attribute)(struct config_item *,
-                                         struct configfs_attribute *,
-                                         char *);
-               ssize_t (*store_attribute)(struct config_item *,
-                                          struct configfs_attribute *,
-                                          const char *, size_t);
                int (*allow_link)(struct config_item *src,
                                  struct config_item *target);
                int (*drop_link)(struct config_item *src,
@@ -183,9 +177,7 @@ The most basic function of a config_item_type is to define what
 operations can be performed on a config_item.  All items that have been
 allocated dynamically will need to provide the ct_item_ops->release()
 method.  This method is called when the config_item's reference count
-reaches zero.  Items that wish to display an attribute need to provide
-the ct_item_ops->show_attribute() method.  Similarly, storing a new
-attribute value uses the store_attribute() method.
+reaches zero.
 
 [struct configfs_attribute]
 
@@ -193,6 +185,8 @@ attribute value uses the store_attribute() method.
                char                    *ca_name;
                struct module           *ca_owner;
                umode_t                  ca_mode;
+               ssize_t (*show)(struct config_item *, char *);
+               ssize_t (*store)(struct config_item *, const char *, size_t);
        };
 
 When a config_item wants an attribute to appear as a file in the item's
@@ -202,10 +196,10 @@ config_item_type->ct_attrs.  When the item appears in configfs, the
 attribute file will appear with the configfs_attribute->ca_name
 filename.  configfs_attribute->ca_mode specifies the file permissions.
 
-If an attribute is readable and the config_item provides a
-ct_item_ops->show_attribute() method, that method will be called
-whenever userspace asks for a read(2) on the attribute.  The converse
-will happen for write(2).
+If an attribute is readable and provides a ->show method, that method will
+be called whenever userspace asks for a read(2) on the attribute.  If an
+attribute is writable and provides a ->store  method, that method will be
+be called whenever userspace asks for a write(2) on the attribute.
 
 [struct config_group]
 
@@ -311,20 +305,10 @@ the subsystem must be ready for it.
 [An Example]
 
 The best example of these basic concepts is the simple_children
-subsystem/group and the simple_child item in configfs_example_explicit.c
-and configfs_example_macros.c.  It shows a trivial object displaying and
-storing an attribute, and a simple group creating and destroying these
-children.
-
-The only difference between configfs_example_explicit.c and
-configfs_example_macros.c is how the attributes of the childless item
-are defined.  The childless item has extended attributes, each with
-their own show()/store() operation.  This follows a convention commonly
-used in sysfs.  configfs_example_explicit.c creates these attributes
-by explicitly defining the structures involved.  Conversely
-configfs_example_macros.c uses some convenience macros from configfs.h
-to define the attributes.  These macros are similar to their sysfs
-counterparts.
+subsystem/group and the simple_child item in
+samples/configfs/configfs_sample.c. It shows a trivial object displaying
+and storing an attribute, and a simple group creating and destroying
+these children.
 
 [Hierarchy Navigation and the Subsystem Mutex]
 
diff --git a/Documentation/filesystems/configfs/configfs_example_explicit.c b/Documentation/filesystems/configfs/configfs_example_explicit.c
deleted file mode 100644 (file)
index 1420233..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * vim: noexpandtab ts=8 sts=0 sw=8:
- *
- * configfs_example_explicit.c - This file is a demonstration module
- *      containing a number of configfs subsystems.  It explicitly defines
- *      each structure without using the helper macros defined in
- *      configfs.h.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 021110-1307, USA.
- *
- * Based on sysfs:
- *     sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
- *
- * configfs Copyright (C) 2005 Oracle.  All rights reserved.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/configfs.h>
-
-
-
-/*
- * 01-childless
- *
- * This first example is a childless subsystem.  It cannot create
- * any config_items.  It just has attributes.
- *
- * Note that we are enclosing the configfs_subsystem inside a container.
- * This is not necessary if a subsystem has no attributes directly
- * on the subsystem.  See the next example, 02-simple-children, for
- * such a subsystem.
- */
-
-struct childless {
-       struct configfs_subsystem subsys;
-       int showme;
-       int storeme;
-};
-
-struct childless_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct childless *, char *);
-       ssize_t (*store)(struct childless *, const char *, size_t);
-};
-
-static inline struct childless *to_childless(struct config_item *item)
-{
-       return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
-}
-
-static ssize_t childless_showme_read(struct childless *childless,
-                                    char *page)
-{
-       ssize_t pos;
-
-       pos = sprintf(page, "%d\n", childless->showme);
-       childless->showme++;
-
-       return pos;
-}
-
-static ssize_t childless_storeme_read(struct childless *childless,
-                                     char *page)
-{
-       return sprintf(page, "%d\n", childless->storeme);
-}
-
-static ssize_t childless_storeme_write(struct childless *childless,
-                                      const char *page,
-                                      size_t count)
-{
-       unsigned long tmp;
-       char *p = (char *) page;
-
-       tmp = simple_strtoul(p, &p, 10);
-       if ((*p != '\0') && (*p != '\n'))
-               return -EINVAL;
-
-       if (tmp > INT_MAX)
-               return -ERANGE;
-
-       childless->storeme = tmp;
-
-       return count;
-}
-
-static ssize_t childless_description_read(struct childless *childless,
-                                         char *page)
-{
-       return sprintf(page,
-"[01-childless]\n"
-"\n"
-"The childless subsystem is the simplest possible subsystem in\n"
-"configfs.  It does not support the creation of child config_items.\n"
-"It only has a few attributes.  In fact, it isn't much different\n"
-"than a directory in /proc.\n");
-}
-
-static struct childless_attribute childless_attr_showme = {
-       .attr   = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
-       .show   = childless_showme_read,
-};
-static struct childless_attribute childless_attr_storeme = {
-       .attr   = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = childless_storeme_read,
-       .store  = childless_storeme_write,
-};
-static struct childless_attribute childless_attr_description = {
-       .attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
-       .show = childless_description_read,
-};
-
-static struct configfs_attribute *childless_attrs[] = {
-       &childless_attr_showme.attr,
-       &childless_attr_storeme.attr,
-       &childless_attr_description.attr,
-       NULL,
-};
-
-static ssize_t childless_attr_show(struct config_item *item,
-                                  struct configfs_attribute *attr,
-                                  char *page)
-{
-       struct childless *childless = to_childless(item);
-       struct childless_attribute *childless_attr =
-               container_of(attr, struct childless_attribute, attr);
-       ssize_t ret = 0;
-
-       if (childless_attr->show)
-               ret = childless_attr->show(childless, page);
-       return ret;
-}
-
-static ssize_t childless_attr_store(struct config_item *item,
-                                   struct configfs_attribute *attr,
-                                   const char *page, size_t count)
-{
-       struct childless *childless = to_childless(item);
-       struct childless_attribute *childless_attr =
-               container_of(attr, struct childless_attribute, attr);
-       ssize_t ret = -EINVAL;
-
-       if (childless_attr->store)
-               ret = childless_attr->store(childless, page, count);
-       return ret;
-}
-
-static struct configfs_item_operations childless_item_ops = {
-       .show_attribute         = childless_attr_show,
-       .store_attribute        = childless_attr_store,
-};
-
-static struct config_item_type childless_type = {
-       .ct_item_ops    = &childless_item_ops,
-       .ct_attrs       = childless_attrs,
-       .ct_owner       = THIS_MODULE,
-};
-
-static struct childless childless_subsys = {
-       .subsys = {
-               .su_group = {
-                       .cg_item = {
-                               .ci_namebuf = "01-childless",
-                               .ci_type = &childless_type,
-                       },
-               },
-       },
-};
-
-
-/* ----------------------------------------------------------------- */
-
-/*
- * 02-simple-children
- *
- * This example merely has a simple one-attribute child.  Note that
- * there is no extra attribute structure, as the child's attribute is
- * known from the get-go.  Also, there is no container for the
- * subsystem, as it has no attributes of its own.
- */
-
-struct simple_child {
-       struct config_item item;
-       int storeme;
-};
-
-static inline struct simple_child *to_simple_child(struct config_item *item)
-{
-       return item ? container_of(item, struct simple_child, item) : NULL;
-}
-
-static struct configfs_attribute simple_child_attr_storeme = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "storeme",
-       .ca_mode = S_IRUGO | S_IWUSR,
-};
-
-static struct configfs_attribute *simple_child_attrs[] = {
-       &simple_child_attr_storeme,
-       NULL,
-};
-
-static ssize_t simple_child_attr_show(struct config_item *item,
-                                     struct configfs_attribute *attr,
-                                     char *page)
-{
-       ssize_t count;
-       struct simple_child *simple_child = to_simple_child(item);
-
-       count = sprintf(page, "%d\n", simple_child->storeme);
-
-       return count;
-}
-
-static ssize_t simple_child_attr_store(struct config_item *item,
-                                      struct configfs_attribute *attr,
-                                      const char *page, size_t count)
-{
-       struct simple_child *simple_child = to_simple_child(item);
-       unsigned long tmp;
-       char *p = (char *) page;
-
-       tmp = simple_strtoul(p, &p, 10);
-       if (!p || (*p && (*p != '\n')))
-               return -EINVAL;
-
-       if (tmp > INT_MAX)
-               return -ERANGE;
-
-       simple_child->storeme = tmp;
-
-       return count;
-}
-
-static void simple_child_release(struct config_item *item)
-{
-       kfree(to_simple_child(item));
-}
-
-static struct configfs_item_operations simple_child_item_ops = {
-       .release                = simple_child_release,
-       .show_attribute         = simple_child_attr_show,
-       .store_attribute        = simple_child_attr_store,
-};
-
-static struct config_item_type simple_child_type = {
-       .ct_item_ops    = &simple_child_item_ops,
-       .ct_attrs       = simple_child_attrs,
-       .ct_owner       = THIS_MODULE,
-};
-
-
-struct simple_children {
-       struct config_group group;
-};
-
-static inline struct simple_children *to_simple_children(struct config_item *item)
-{
-       return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
-}
-
-static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
-{
-       struct simple_child *simple_child;
-
-       simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
-       if (!simple_child)
-               return ERR_PTR(-ENOMEM);
-
-       config_item_init_type_name(&simple_child->item, name,
-                                  &simple_child_type);
-
-       simple_child->storeme = 0;
-
-       return &simple_child->item;
-}
-
-static struct configfs_attribute simple_children_attr_description = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "description",
-       .ca_mode = S_IRUGO,
-};
-
-static struct configfs_attribute *simple_children_attrs[] = {
-       &simple_children_attr_description,
-       NULL,
-};
-
-static ssize_t simple_children_attr_show(struct config_item *item,
-                                        struct configfs_attribute *attr,
-                                        char *page)
-{
-       return sprintf(page,
-"[02-simple-children]\n"
-"\n"
-"This subsystem allows the creation of child config_items.  These\n"
-"items have only one attribute that is readable and writeable.\n");
-}
-
-static void simple_children_release(struct config_item *item)
-{
-       kfree(to_simple_children(item));
-}
-
-static struct configfs_item_operations simple_children_item_ops = {
-       .release        = simple_children_release,
-       .show_attribute = simple_children_attr_show,
-};
-
-/*
- * Note that, since no extra work is required on ->drop_item(),
- * no ->drop_item() is provided.
- */
-static struct configfs_group_operations simple_children_group_ops = {
-       .make_item      = simple_children_make_item,
-};
-
-static struct config_item_type simple_children_type = {
-       .ct_item_ops    = &simple_children_item_ops,
-       .ct_group_ops   = &simple_children_group_ops,
-       .ct_attrs       = simple_children_attrs,
-       .ct_owner       = THIS_MODULE,
-};
-
-static struct configfs_subsystem simple_children_subsys = {
-       .su_group = {
-               .cg_item = {
-                       .ci_namebuf = "02-simple-children",
-                       .ci_type = &simple_children_type,
-               },
-       },
-};
-
-
-/* ----------------------------------------------------------------- */
-
-/*
- * 03-group-children
- *
- * This example reuses the simple_children group from above.  However,
- * the simple_children group is not the subsystem itself, it is a
- * child of the subsystem.  Creation of a group in the subsystem creates
- * a new simple_children group.  That group can then have simple_child
- * children of its own.
- */
-
-static struct config_group *group_children_make_group(struct config_group *group, const char *name)
-{
-       struct simple_children *simple_children;
-
-       simple_children = kzalloc(sizeof(struct simple_children),
-                                 GFP_KERNEL);
-       if (!simple_children)
-               return ERR_PTR(-ENOMEM);
-
-       config_group_init_type_name(&simple_children->group, name,
-                                   &simple_children_type);
-
-       return &simple_children->group;
-}
-
-static struct configfs_attribute group_children_attr_description = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "description",
-       .ca_mode = S_IRUGO,
-};
-
-static struct configfs_attribute *group_children_attrs[] = {
-       &group_children_attr_description,
-       NULL,
-};
-
-static ssize_t group_children_attr_show(struct config_item *item,
-                                       struct configfs_attribute *attr,
-                                       char *page)
-{
-       return sprintf(page,
-"[03-group-children]\n"
-"\n"
-"This subsystem allows the creation of child config_groups.  These\n"
-"groups are like the subsystem simple-children.\n");
-}
-
-static struct configfs_item_operations group_children_item_ops = {
-       .show_attribute = group_children_attr_show,
-};
-
-/*
- * Note that, since no extra work is required on ->drop_item(),
- * no ->drop_item() is provided.
- */
-static struct configfs_group_operations group_children_group_ops = {
-       .make_group     = group_children_make_group,
-};
-
-static struct config_item_type group_children_type = {
-       .ct_item_ops    = &group_children_item_ops,
-       .ct_group_ops   = &group_children_group_ops,
-       .ct_attrs       = group_children_attrs,
-       .ct_owner       = THIS_MODULE,
-};
-
-static struct configfs_subsystem group_children_subsys = {
-       .su_group = {
-               .cg_item = {
-                       .ci_namebuf = "03-group-children",
-                       .ci_type = &group_children_type,
-               },
-       },
-};
-
-/* ----------------------------------------------------------------- */
-
-/*
- * We're now done with our subsystem definitions.
- * For convenience in this module, here's a list of them all.  It
- * allows the init function to easily register them.  Most modules
- * will only have one subsystem, and will only call register_subsystem
- * on it directly.
- */
-static struct configfs_subsystem *example_subsys[] = {
-       &childless_subsys.subsys,
-       &simple_children_subsys,
-       &group_children_subsys,
-       NULL,
-};
-
-static int __init configfs_example_init(void)
-{
-       int ret;
-       int i;
-       struct configfs_subsystem *subsys;
-
-       for (i = 0; example_subsys[i]; i++) {
-               subsys = example_subsys[i];
-
-               config_group_init(&subsys->su_group);
-               mutex_init(&subsys->su_mutex);
-               ret = configfs_register_subsystem(subsys);
-               if (ret) {
-                       printk(KERN_ERR "Error %d while registering subsystem %s\n",
-                              ret,
-                              subsys->su_group.cg_item.ci_namebuf);
-                       goto out_unregister;
-               }
-       }
-
-       return 0;
-
-out_unregister:
-       for (i--; i >= 0; i--)
-               configfs_unregister_subsystem(example_subsys[i]);
-
-       return ret;
-}
-
-static void __exit configfs_example_exit(void)
-{
-       int i;
-
-       for (i = 0; example_subsys[i]; i++)
-               configfs_unregister_subsystem(example_subsys[i]);
-}
-
-module_init(configfs_example_init);
-module_exit(configfs_example_exit);
-MODULE_LICENSE("GPL");
index 6db0e5d1da07ee52d13f5997b84b3b10ef43e2dd..28091457b71ae89357530b351322f6a59c35bc9e 100644 (file)
@@ -1,4 +1,5 @@
-Written by: Neil Brown <neilb@suse.de>
+Written by: Neil Brown
+Please see MAINTAINERS file for where to send questions.
 
 Overlay Filesystem
 ==================
index 6a4b1af724f8626c61f04bc2cb47a353f26a4826..1bba38dd263727cac57958e8f26a6ca75092c5e8 100644 (file)
@@ -32,6 +32,7 @@ Supported adapters:
   * Intel Sunrise Point-LP (PCH)
   * Intel DNV (SOC)
   * Intel Broxton (SOC)
+  * Intel Lewisburg (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index f8aae632f02f678000f9de7a8d507a5ea0bb9404..742f69d18fc8989ae28d9c0662d6bf334109dddd 100644 (file)
@@ -1583,9 +1583,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                hwp_only
                        Only load intel_pstate on systems which support
                        hardware P state control (HWP) if available.
-               no_acpi
-                       Don't use ACPI processor performance control objects
-                       _PSS and _PPC specified limits.
 
        intremap=       [X86-64, Intel-IOMMU]
                        on      enable Interrupt Remapping (default)
index 4636b94518da706012dc0677ef9fc6bd5265b1f4..05fd83bb35967a2d92c9fac588a15fb2b3532beb 100644 (file)
@@ -681,7 +681,7 @@ solution for a couple of reasons:
     addr.can_family = AF_CAN;
     addr.can_ifindex = ifr.ifr_ifindex;
 
-    connect(s, (struct sockaddr *)&addr, sizeof(addr))
+    connect(s, (struct sockaddr *)&addr, sizeof(addr));
 
     (..)
 
index 197a0b6b058215c60f3d79f3f40cc2aca4504013..e894de69915a38d3abd81b40e4b0e21a261fadcd 100644 (file)
@@ -62,6 +62,12 @@ DAX: File system extensions to bypass the page cache and block layer to
 mmap persistent memory, from a PMEM block device, directly into a
 process address space.
 
+DSM: Device Specific Method: ACPI method to to control specific
+device - in this case the firmware.
+
+DCR: NVDIMM Control Region Structure defined in ACPI 6 Section 5.2.25.5.
+It defines a vendor-id, device-id, and interface format for a given DIMM.
+
 BTT: Block Translation Table: Persistent memory is byte addressable.
 Existing software may have an expectation that the power-fail-atomicity
 of writes is at least one sector, 512 bytes.  The BTT is an indirection
@@ -133,16 +139,16 @@ device driver:
     registered, can be immediately attached to nd_pmem.
 
     2. BLK (nd_blk.ko): This driver performs I/O using a set of platform
-    defined apertures.  A set of apertures will all access just one DIMM.
-    Multiple windows allow multiple concurrent accesses, much like
+    defined apertures.  A set of apertures will access just one DIMM.
+    Multiple windows (apertures) allow multiple concurrent accesses, much like
     tagged-command-queuing, and would likely be used by different threads or
     different CPUs.
 
     The NFIT specification defines a standard format for a BLK-aperture, but
     the spec also allows for vendor specific layouts, and non-NFIT BLK
-    implementations may other designs for BLK I/O.  For this reason "nd_blk"
-    calls back into platform-specific code to perform the I/O.  One such
-    implementation is defined in the "Driver Writer's Guide" and "DSM
+    implementations may have other designs for BLK I/O.  For this reason
+    "nd_blk" calls back into platform-specific code to perform the I/O.
+    One such implementation is defined in the "Driver Writer's Guide" and "DSM
     Interface Example".
 
 
@@ -152,7 +158,7 @@ Why BLK?
 While PMEM provides direct byte-addressable CPU-load/store access to
 NVDIMM storage, it does not provide the best system RAS (recovery,
 availability, and serviceability) model.  An access to a corrupted
-system-physical-address address causes a cpu exception while an access
+system-physical-address address causes a CPU exception while an access
 to a corrupted address through an BLK-aperture causes that block window
 to raise an error status in a register.  The latter is more aligned with
 the standard error model that host-bus-adapter attached disks present.
@@ -162,7 +168,7 @@ data could be interleaved in an opaque hardware specific manner across
 several DIMMs.
 
 PMEM vs BLK
-BLK-apertures solve this RAS problem, but their presence is also the
+BLK-apertures solve these RAS problems, but their presence is also the
 major contributing factor to the complexity of the ND subsystem.  They
 complicate the implementation because PMEM and BLK alias in DPA space.
 Any given DIMM's DPA-range may contribute to one or more
@@ -220,8 +226,8 @@ socket.  Each unique interface (BLK or PMEM) to DPA space is identified
 by a region device with a dynamically assigned id (REGION0 - REGION5).
 
     1. The first portion of DIMM0 and DIMM1 are interleaved as REGION0. A
-    single PMEM namespace is created in the REGION0-SPA-range that spans
-    DIMM0 and DIMM1 with a user-specified name of "pm0.0". Some of that
+    single PMEM namespace is created in the REGION0-SPA-range that spans most
+    of DIMM0 and DIMM1 with a user-specified name of "pm0.0". Some of that
     interleaved system-physical-address range is reclaimed as BLK-aperture
     accessed space starting at DPA-offset (a) into each DIMM.  In that
     reclaimed space we create two BLK-aperture "namespaces" from REGION2 and
@@ -230,13 +236,13 @@ by a region device with a dynamically assigned id (REGION0 - REGION5).
 
     2. In the last portion of DIMM0 and DIMM1 we have an interleaved
     system-physical-address range, REGION1, that spans those two DIMMs as
-    well as DIMM2 and DIMM3.  Some of REGION1 allocated to a PMEM namespace
-    named "pm1.0" the rest is reclaimed in 4 BLK-aperture namespaces (for
+    well as DIMM2 and DIMM3.  Some of REGION1 is allocated to a PMEM namespace
+    named "pm1.0", the rest is reclaimed in 4 BLK-aperture namespaces (for
     each DIMM in the interleave set), "blk2.1", "blk3.1", "blk4.0", and
     "blk5.0".
 
     3. The portion of DIMM2 and DIMM3 that do not participate in the REGION1
-    interleaved system-physical-address range (i.e. the DPA address below
+    interleaved system-physical-address range (i.e. the DPA address past
     offset (b) are also included in the "blk4.0" and "blk5.0" namespaces.
     Note, that this example shows that BLK-aperture namespaces don't need to
     be contiguous in DPA-space.
@@ -252,15 +258,15 @@ LIBNVDIMM Kernel Device Model and LIBNDCTL Userspace API
 
 What follows is a description of the LIBNVDIMM sysfs layout and a
 corresponding object hierarchy diagram as viewed through the LIBNDCTL
-api.  The example sysfs paths and diagrams are relative to the Example
+API.  The example sysfs paths and diagrams are relative to the Example
 NVDIMM Platform which is also the LIBNVDIMM bus used in the LIBNDCTL unit
 test.
 
 LIBNDCTL: Context
-Every api call in the LIBNDCTL library requires a context that holds the
+Every API call in the LIBNDCTL library requires a context that holds the
 logging parameters and other library instance state.  The library is
 based on the libabc template:
-https://git.kernel.org/cgit/linux/kernel/git/kay/libabc.git/
+https://git.kernel.org/cgit/linux/kernel/git/kay/libabc.git
 
 LIBNDCTL: instantiate a new library context example
 
@@ -409,7 +415,7 @@ Bit 31:28 Reserved
 LIBNVDIMM/LIBNDCTL: Region
 ----------------------
 
-A generic REGION device is registered for each PMEM range orBLK-aperture
+A generic REGION device is registered for each PMEM range or BLK-aperture
 set.  Per the example there are 6 regions: 2 PMEM and 4 BLK-aperture
 sets on the "nfit_test.0" bus.  The primary role of regions are to be a
 container of "mappings".  A mapping is a tuple of <DIMM,
@@ -509,7 +515,7 @@ At first glance it seems since NFIT defines just PMEM and BLK interface
 types that we should simply name REGION devices with something derived
 from those type names.  However, the ND subsystem explicitly keeps the
 REGION name generic and expects userspace to always consider the
-region-attributes for 4 reasons:
+region-attributes for four reasons:
 
     1. There are already more than two REGION and "namespace" types.  For
     PMEM there are two subtypes.  As mentioned previously we have PMEM where
@@ -698,8 +704,8 @@ static int configure_namespace(struct ndctl_region *region,
 
 Why the Term "namespace"?
 
-    1. Why not "volume" for instance?  "volume" ran the risk of confusing ND
-    as a volume manager like device-mapper.
+    1. Why not "volume" for instance?  "volume" ran the risk of confusing
+    ND (libnvdimm subsystem) to a volume manager like device-mapper.
 
     2. The term originated to describe the sub-devices that can be created
     within a NVME controller (see the nvme specification:
@@ -774,13 +780,14 @@ block" needs to be destroyed.  Note, that to destroy a BTT the media
 needs to be written in raw mode.  By default, the kernel will autodetect
 the presence of a BTT and disable raw mode.  This autodetect behavior
 can be suppressed by enabling raw mode for the namespace via the
-ndctl_namespace_set_raw_mode() api.
+ndctl_namespace_set_raw_mode() API.
 
 
 Summary LIBNDCTL Diagram
 ------------------------
 
-For the given example above, here is the view of the objects as seen by the LIBNDCTL api:
+For the given example above, here is the view of the objects as seen by the
+LIBNDCTL API:
             +---+
             |CTX|    +---------+   +--------------+  +---------------+
             +-+-+  +-> REGION0 +---> NAMESPACE0.0 +--> PMEM8 "pm0.0" |
index f29fa550665af92dba9248113de5be639c10c885..b3211af63b7956c1f4325a87fb08b52de959692a 100644 (file)
@@ -569,7 +569,9 @@ Debugging code is now compiled in by default but debugging is turned off
 with the kernel module parameter debug_flag defaulting to 0.  Debugging
 can still be switched on and off with an ioctl.  To enable debug at
 module load time add debug_flag=1 to the module load options, the
-debugging output is not voluminous.
+debugging output is not voluminous. Debugging can also be enabled
+and disabled by writing a '0' (disable) or '1' (enable) to the sysfs
+file /sys/bus/scsi/drivers/st/debug_flag.
 
 If the tape seems to hang, I would be very interested to hear where
 the driver is waiting. With the command 'ps -l' you can see the state
index cda56df9b8a7ce591f3eb254cad1d423c0a856c5..7d370c9b1450c5fc5a2230d086026fa1c7d59ab7 100755 (executable)
@@ -203,8 +203,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "#include <scsi/scsi_proto.h>\n\n"
        buf += "#include <target/target_core_base.h>\n"
        buf += "#include <target/target_core_fabric.h>\n"
-       buf += "#include <target/target_core_fabric_configfs.h>\n"
-       buf += "#include <target/configfs_macros.h>\n\n"
        buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
        buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
 
@@ -283,19 +281,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "                                struct " + fabric_mod_name + "_" + fabric_mod_port + ", " + fabric_mod_port + "_wwn);\n"
        buf += "        kfree(" + fabric_mod_port + ");\n"
        buf += "}\n\n"
-       buf += "static ssize_t " + fabric_mod_name + "_wwn_show_attr_version(\n"
-       buf += "        struct target_fabric_configfs *tf,\n"
-       buf += "        char *page)\n"
-       buf += "{\n"
-       buf += "        return sprintf(page, \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
-       buf += "                \"on \"UTS_RELEASE\"\\n\", " + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
-       buf += "                utsname()->machine);\n"
-       buf += "}\n\n"
-       buf += "TF_WWN_ATTR_RO(" + fabric_mod_name + ", version);\n\n"
-       buf += "static struct configfs_attribute *" + fabric_mod_name + "_wwn_attrs[] = {\n"
-       buf += "        &" + fabric_mod_name + "_wwn_version.attr,\n"
-       buf += "        NULL,\n"
-       buf += "};\n\n"
 
        buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
        buf += "        .module                         = THIS_MODULE,\n"
@@ -328,8 +313,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        .fabric_drop_wwn                = " + fabric_mod_name + "_drop_" + fabric_mod_port + ",\n"
        buf += "        .fabric_make_tpg                = " + fabric_mod_name + "_make_tpg,\n"
        buf += "        .fabric_drop_tpg                = " + fabric_mod_name + "_drop_tpg,\n"
-       buf += "\n"
-       buf += "        .tfc_wwn_attrs                  = " + fabric_mod_name + "_wwn_attrs,\n"
        buf += "};\n\n"
 
        buf += "static int __init " + fabric_mod_name + "_init(void)\n"
index 35fe7ae0492e066cfb716913fe2fa7b7cd2a9256..cba790b42f23d5980088588d01d97084cd8423d2 100644 (file)
@@ -1931,7 +1931,7 @@ S:        Supported
 F:     drivers/i2c/busses/i2c-at91.c
 
 ATMEL ISI DRIVER
-M:     Josh Wu <josh.wu@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@atmel.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 F:     drivers/media/platform/soc_camera/atmel-isi.c
@@ -1950,7 +1950,8 @@ S:        Supported
 F:     drivers/net/ethernet/cadence/
 
 ATMEL NAND DRIVER
-M:     Josh Wu <josh.wu@atmel.com>
+M:     Wenyou Yang <wenyou.yang@atmel.com>
+M:     Josh Wu <rainyfeeling@outlook.com>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
 F:     drivers/mtd/nand/atmel_nand*
@@ -2210,6 +2211,7 @@ F:        drivers/leds/leds-blinkm.c
 
 BLOCK LAYER
 M:     Jens Axboe <axboe@kernel.dk>
+L:     linux-block@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
 S:     Maintained
 F:     block/
@@ -2448,7 +2450,9 @@ F:        drivers/firmware/broadcom/*
 
 BROADCOM STB NAND FLASH DRIVER
 M:     Brian Norris <computersforpeace@gmail.com>
+M:     Kamal Dasu <kdasu.kdev@gmail.com>
 L:     linux-mtd@lists.infradead.org
+L:     bcm-kernel-feedback-list@broadcom.com
 S:     Maintained
 F:     drivers/mtd/nand/brcmnand/
 
@@ -2545,7 +2549,7 @@ F:        arch/c6x/
 
 CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
 M:     David Howells <dhowells@redhat.com>
-L:     linux-cachefs@redhat.com
+L:     linux-cachefs@redhat.com (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/filesystems/caching/cachefiles.txt
 F:     fs/cachefiles/
@@ -2928,10 +2932,9 @@ S:       Maintained
 F:     drivers/platform/x86/compal-laptop.c
 
 CONEXANT ACCESSRUNNER USB DRIVER
-M:     Simon Arlott <cxacru@fire.lp0.eu>
 L:     accessrunner-general@lists.sourceforge.net
 W:     http://accessrunner.sourceforge.net/
-S:     Maintained
+S:     Orphan
 F:     drivers/usb/atm/cxacru.c
 
 CONFIGFS
@@ -4408,6 +4411,7 @@ K:        fmc_d.*register
 
 FPGA MANAGER FRAMEWORK
 M:     Alan Tull <atull@opensource.altera.com>
+R:     Moritz Fischer <moritz.fischer@ettus.com>
 S:     Maintained
 F:     drivers/fpga/
 F:     include/linux/fpga/fpga-mgr.h
@@ -4558,7 +4562,7 @@ F:        include/linux/frontswap.h
 
 FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
 M:     David Howells <dhowells@redhat.com>
-L:     linux-cachefs@redhat.com
+L:     linux-cachefs@redhat.com (moderated for non-subscribers)
 S:     Supported
 F:     Documentation/filesystems/caching/
 F:     fs/fscache/
@@ -5505,7 +5509,8 @@ S:        Supported
 F:     drivers/idle/intel_idle.c
 
 INTEL PSTATE DRIVER
-M:     Kristen Carlson Accardi <kristen@linux.intel.com>
+M:     Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+M:     Len Brown <lenb@kernel.org>
 L:     linux-pm@vger.kernel.org
 S:     Supported
 F:     drivers/cpufreq/intel_pstate.c
@@ -5709,13 +5714,6 @@ M:       Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
 S:     Maintained
 F:     net/ipv4/netfilter/ipt_MASQUERADE.c
 
-IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER
-M:     Francois Romieu <romieu@fr.zoreil.com>
-M:     Sorbica Shieh <sorbica@icplus.com.tw>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     drivers/net/ethernet/icplus/ipg.*
-
 IPATH DRIVER
 M:     Mike Marciniszyn <infinipath@intel.com>
 L:     linux-rdma@vger.kernel.org
@@ -6369,6 +6367,7 @@ F:        arch/*/include/asm/pmem.h
 LIGHTNVM PLATFORM SUPPORT
 M:     Matias Bjorling <mb@lightnvm.io>
 W:     http://github/OpenChannelSSD
+L:     linux-block@vger.kernel.org
 S:     Maintained
 F:     drivers/lightnvm/
 F:     include/linux/lightnvm.h
@@ -6921,13 +6920,21 @@ F:      drivers/scsi/megaraid.*
 F:     drivers/scsi/megaraid/
 
 MELLANOX ETHERNET DRIVER (mlx4_en)
-M:     Amir Vadai <amirv@mellanox.com>
+M:     Eugenia Emantayev <eugenia@mellanox.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
 F:     drivers/net/ethernet/mellanox/mlx4/en_*
 
+MELLANOX ETHERNET DRIVER (mlx5e)
+M:     Saeed Mahameed <saeedm@mellanox.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+W:     http://www.mellanox.com
+Q:     http://patchwork.ozlabs.org/project/netdev/list/
+F:     drivers/net/ethernet/mellanox/mlx5/core/en_*
+
 MELLANOX ETHERNET SWITCH DRIVERS
 M:     Jiri Pirko <jiri@mellanox.com>
 M:     Ido Schimmel <idosch@mellanox.com>
@@ -7899,6 +7906,18 @@ S:       Maintained
 F:     net/openvswitch/
 F:     include/uapi/linux/openvswitch.h
 
+OPERATING PERFORMANCE POINTS (OPP)
+M:     Viresh Kumar <vireshk@kernel.org>
+M:     Nishanth Menon <nm@ti.com>
+M:     Stephen Boyd <sboyd@codeaurora.org>
+L:     linux-pm@vger.kernel.org
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git
+F:     drivers/base/power/opp/
+F:     include/linux/pm_opp.h
+F:     Documentation/power/opp.txt
+F:     Documentation/devicetree/bindings/opp/
+
 OPL4 DRIVER
 M:     Clemens Ladisch <clemens@ladisch.de>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -9312,7 +9331,6 @@ F:        drivers/i2c/busses/i2c-designware-*
 F:     include/linux/platform_data/i2c-designware.h
 
 SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
-M:     Seungwon Jeon <tgih.jun@samsung.com>
 M:     Jaehoon Chung <jh80.chung@samsung.com>
 L:     linux-mmc@vger.kernel.org
 S:     Maintained
@@ -10298,7 +10316,7 @@ F:      include/net/switchdev.h
 
 SYNOPSYS ARC ARCHITECTURE
 M:     Vineet Gupta <vgupta@synopsys.com>
-L:     linux-snps-arc@lists.infraded.org
+L:     linux-snps-arc@lists.infradead.org
 S:     Supported
 F:     arch/arc/
 F:     Documentation/devicetree/bindings/arc/*
index 26de6c3298b1284c8971b47ec9271ea5d3adf90f..2ffdf9d6f339f7254f1a08ff979bf424f0c5a33d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
-PATCHLEVEL = 3
+PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc2
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
index c92c0ef1e9d290b2db437001338cf477c1df9513..f1ac9818b751e1fab854f2c1a4440b9ca8af3e85 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
index cfac24e0e7b6565a48c3a22f6251e8992fbb84bb..323486d6ee83419a9e50d5c53fa042f53e08ebed 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
index 9922a118a15a3d28c99c85f1c67407142e75fb86..66191cd0447eaabc524a36ec497e7047043dc9a4 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
index f761a7c70761862139ffeb7a2f89d2b159ffec71..f68838e8068af53eb2ebb29c83d88cb10dc0bfac 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
index dc6f74f412837b51486634851a1e10ddc4341f10..96bd1c20fb0badeb5d3ebf41f2671f6558939c22 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
index 3fef0a210c5654bda4e0bc085d3910d2b336a59c..fcae66683ca0bd5865924a88816a388e763604cd 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
index 51784837daaec1e0b3fd0434b60e41b5b6e15610..b01b659168ea4a1c36ac85e0ee41c545aa697ec8 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
index ef35ef3923ddca3a6fa84bd121b682681c861fc7..a07f20de221ba1f0b0963ca1f1d44053c6b1b89a 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_CROSS_MEMORY_ATTACH is not set
index 634509e5e572ef02911e1a79906d54faf8523951..f36c047b33cad0c469bd2368bb3e5fa4260535e5 100644 (file)
@@ -1,4 +1,4 @@
-CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
+CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_CROSS_MEMORY_ATTACH is not set
index ad481c24070dd1f369fefab436160f6d60f9dc2c..258b0e5ad3329a614e59204df55d91873e969623 100644 (file)
@@ -37,6 +37,9 @@
 #define ISA_INIT_STATUS_BITS   (STATUS_IE_MASK | STATUS_AD_MASK | \
                                        (ARCV2_IRQ_DEF_PRIO << 1))
 
+/* SLEEP needs default irq priority (<=) which can interrupt the doze */
+#define ISA_SLEEP_ARG          (0x10 | ARCV2_IRQ_DEF_PRIO)
+
 #ifndef __ASSEMBLY__
 
 /*
index d8c608174617783496b8855bc6ed19de9b6f67cd..c1d36458bfb7aa665acb30a2234660034a19aecd 100644 (file)
@@ -43,6 +43,8 @@
 
 #define ISA_INIT_STATUS_BITS   STATUS_IE_MASK
 
+#define ISA_SLEEP_ARG          0x3
+
 #ifndef __ASSEMBLY__
 
 /******************************************************************
index 44545354e9e85616b703f531787ed74def265bf5..1d694c1ef6d6bf33ccb17745db6e58e816915875 100644 (file)
@@ -57,11 +57,7 @@ struct task_struct;
  * A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
  * get optimised away by gcc
  */
-#ifdef CONFIG_SMP
 #define cpu_relax()    __asm__ __volatile__ ("" : : : "memory")
-#else
-#define cpu_relax()    do { } while (0)
-#endif
 
 #define cpu_relax_lowlatency() cpu_relax()
 
index c14a5bea0c76792ead17b42e1f548e38960cc194..5d446df2c41353a15edfc5a5f7b05abd24b16df3 100644 (file)
@@ -58,8 +58,6 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
                "st      sp, [r24]       \n\t"
 #endif
 
-               "sync   \n\t"
-
                /*
                 * setup _current_task with incoming tsk.
                 * optionally, set r25 to that as well
index e248594097e7d69c66b2f46044dbfe4782008bd0..e6890b1f8650647774b48678c88e805f6b16de3a 100644 (file)
@@ -44,9 +44,6 @@ __switch_to:
        * don't need to do anything special to return it
        */
 
-       /* hardware memory barrier */
-       sync
-
        /*
         * switch to new task, contained in r1
         * Temp reg r3 is required to get the ptr to store val
index 445e63a10754fbdb0be82663af03f489282cfce5..cbfec79137bf77735fa675d0eb2be57da217ba63 100644 (file)
@@ -91,6 +91,25 @@ ENTRY(EV_DCError)
        flag 1
 END(EV_DCError)
 
+; ---------------------------------------------
+; Memory Error Exception Handler
+;   - Unlike ARCompact, handles Bus errors for both User/Kernel mode,
+;     Instruction fetch or Data access, under a single Exception Vector
+; ---------------------------------------------
+
+ENTRY(mem_service)
+
+       EXCEPTION_PROLOGUE
+
+       lr  r0, [efa]
+       mov r1, sp
+
+       FAKE_RET_FROM_EXCPN
+
+       bl  do_memory_error
+       b   ret_from_exception
+END(mem_service)
+
 ENTRY(EV_Misaligned)
 
        EXCEPTION_PROLOGUE
index 59f52035b4ea34a582b50b80e5db48893c1dc7bf..431433929189c8b63e8b3efe41ef03030fa8b86f 100644 (file)
@@ -142,16 +142,12 @@ int1_saved_reg:
        .zero 4
 
 /* Each Interrupt level needs its own scratch */
-#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
-
 ARCFP_DATA int2_saved_reg
        .type   int2_saved_reg, @object
        .size   int2_saved_reg, 4
 int2_saved_reg:
        .zero 4
 
-#endif
-
 ; ---------------------------------------------
        .section .text, "ax",@progbits
 
@@ -215,6 +211,31 @@ END(handle_interrupt_level2)
 
 #endif
 
+; ---------------------------------------------
+; User Mode Memory Bus Error Interrupt Handler
+; (Kernel mode memory errors handled via seperate exception vectors)
+; ---------------------------------------------
+ENTRY(mem_service)
+
+       INTERRUPT_PROLOGUE 2
+
+       mov r0, ilink2
+       mov r1, sp
+
+       ; User process needs to be killed with SIGBUS, but first need to get
+       ; out of the L2 interrupt context (drop to pure kernel mode) and jump
+       ; off to "C" code where SIGBUS in enqueued
+       lr  r3, [status32]
+       bclr r3, r3, STATUS_A2_BIT
+       or  r3, r3, (STATUS_E1_MASK|STATUS_E2_MASK)
+       sr  r3, [status32_l2]
+       mov ilink2, 1f
+       rtie
+1:
+       bl  do_memory_error
+       b   ret_from_exception
+END(mem_service)
+
 ; ---------------------------------------------
 ;  Level 1 ISR
 ; ---------------------------------------------
index 589abf5172d6a19047337e315fb2ff5ad1fab8a4..2efb0625331d6d5a6b6f8b1558a05e6e3cc5679e 100644 (file)
@@ -92,23 +92,6 @@ ENTRY(instr_service)
        b   ret_from_exception
 END(instr_service)
 
-; ---------------------------------------------
-; Memory Error Exception Handler
-; ---------------------------------------------
-
-ENTRY(mem_service)
-
-       EXCEPTION_PROLOGUE
-
-       lr  r0, [efa]
-       mov r1, sp
-
-       FAKE_RET_FROM_EXCPN
-
-       bl  do_memory_error
-       b   ret_from_exception
-END(mem_service)
-
 ; ---------------------------------------------
 ; Machine Check Exception Handler
 ; ---------------------------------------------
index 91d5a0f1f3f79cdd454e99e7781b2e3741caae76..a3f750e76b683dd25a45584b71014532214b20ac 100644 (file)
@@ -44,11 +44,10 @@ SYSCALL_DEFINE0(arc_gettls)
 void arch_cpu_idle(void)
 {
        /* sleep, but enable all interrupts before committing */
-       if (is_isa_arcompact()) {
-               __asm__("sleep 0x3");
-       } else {
-               __asm__("sleep 0x10");
-       }
+       __asm__ __volatile__(
+               "sleep %0       \n"
+               :
+               :"I"(ISA_SLEEP_ARG)); /* can't be "r" has to be embedded const */
 }
 
 asmlinkage void ret_from_fork(void);
index 93c6ea52b6719e4e238d6076fda6c3b981ac48fe..7352475451f6c3798885c97b04c11ddd53146990 100644 (file)
@@ -986,42 +986,13 @@ int arc_unwind(struct unwind_frame_info *frame)
                                                            (const u8 *)(fde +
                                                                         1) +
                                                            *fde, ptrType);
-                               if (pc >= endLoc)
+                               if (pc >= endLoc) {
                                        fde = NULL;
-                       } else
-                               fde = NULL;
-               }
-               if (fde == NULL) {
-                       for (fde = table->address, tableSize = table->size;
-                            cie = NULL, tableSize > sizeof(*fde)
-                            && tableSize - sizeof(*fde) >= *fde;
-                            tableSize -= sizeof(*fde) + *fde,
-                            fde += 1 + *fde / sizeof(*fde)) {
-                               cie = cie_for_fde(fde, table);
-                               if (cie == &bad_cie) {
                                        cie = NULL;
-                                       break;
                                }
-                               if (cie == NULL
-                                   || cie == &not_fde
-                                   || (ptrType = fde_pointer_type(cie)) < 0)
-                                       continue;
-                               ptr = (const u8 *)(fde + 2);
-                               startLoc = read_pointer(&ptr,
-                                                       (const u8 *)(fde + 1) +
-                                                       *fde, ptrType);
-                               if (!startLoc)
-                                       continue;
-                               if (!(ptrType & DW_EH_PE_indirect))
-                                       ptrType &=
-                                           DW_EH_PE_FORM | DW_EH_PE_signed;
-                               endLoc =
-                                   startLoc + read_pointer(&ptr,
-                                                           (const u8 *)(fde +
-                                                                        1) +
-                                                           *fde, ptrType);
-                               if (pc >= startLoc && pc < endLoc)
-                                       break;
+                       } else {
+                               fde = NULL;
+                               cie = NULL;
                        }
                }
        }
index 0cab0b8a57c5665e6686e9bef843fbfa51f141fd..f96c75edf30af5b38ecb7aa73710bc523dbfd366 100644 (file)
@@ -50,26 +50,26 @@ ENTRY(memcpy)
 
 ;;; if size <= 8
        cmp     r2, 8
-       bls.d   @smallchunk
+       bls.d   @.Lsmallchunk
        mov.f   lp_count, r2
 
        and.f   r4, r0, 0x03
        rsub    lp_count, r4, 4
-       lpnz    @aligndestination
+       lpnz    @.Laligndestination
        ;; LOOP BEGIN
        ldb.ab  r5, [r1,1]
        sub     r2, r2, 1
        stb.ab  r5, [r3,1]
-aligndestination:
+.Laligndestination:
 
 ;;; Check the alignment of the source
        and.f   r4, r1, 0x03
-       bnz.d   @sourceunaligned
+       bnz.d   @.Lsourceunaligned
 
 ;;; CASE 0: Both source and destination are 32bit aligned
 ;;; Convert len to Dwords, unfold x4
        lsr.f   lp_count, r2, ZOLSHFT
-       lpnz    @copy32_64bytes
+       lpnz    @.Lcopy32_64bytes
        ;; LOOP START
        LOADX (r6, r1)
        PREFETCH_READ (r1)
@@ -81,25 +81,25 @@ aligndestination:
        STOREX (r8, r3)
        STOREX (r10, r3)
        STOREX (r4, r3)
-copy32_64bytes:
+.Lcopy32_64bytes:
 
        and.f   lp_count, r2, ZOLAND ;Last remaining 31 bytes
-smallchunk:
-       lpnz    @copyremainingbytes
+.Lsmallchunk:
+       lpnz    @.Lcopyremainingbytes
        ;; LOOP START
        ldb.ab  r5, [r1,1]
        stb.ab  r5, [r3,1]
-copyremainingbytes:
+.Lcopyremainingbytes:
 
        j       [blink]
 ;;; END CASE 0
 
-sourceunaligned:
+.Lsourceunaligned:
        cmp     r4, 2
-       beq.d   @unalignedOffby2
+       beq.d   @.LunalignedOffby2
        sub     r2, r2, 1
 
-       bhi.d   @unalignedOffby3
+       bhi.d   @.LunalignedOffby3
        ldb.ab  r5, [r1, 1]
 
 ;;; CASE 1: The source is unaligned, off by 1
@@ -114,7 +114,7 @@ sourceunaligned:
        or      r5, r5, r6
 
        ;; Both src and dst are aligned
-       lpnz    @copy8bytes_1
+       lpnz    @.Lcopy8bytes_1
        ;; LOOP START
        ld.ab   r6, [r1, 4]
        prefetch [r1, 28]       ;Prefetch the next read location
@@ -131,7 +131,7 @@ sourceunaligned:
 
        st.ab   r7, [r3, 4]
        st.ab   r9, [r3, 4]
-copy8bytes_1:
+.Lcopy8bytes_1:
 
        ;; Write back the remaining 16bits
        EXTRACT_1 (r6, r5, 16)
@@ -141,14 +141,14 @@ copy8bytes_1:
        stb.ab  r5, [r3, 1]
 
        and.f   lp_count, r2, 0x07 ;Last 8bytes
-       lpnz    @copybytewise_1
+       lpnz    @.Lcopybytewise_1
        ;; LOOP START
        ldb.ab  r6, [r1,1]
        stb.ab  r6, [r3,1]
-copybytewise_1:
+.Lcopybytewise_1:
        j       [blink]
 
-unalignedOffby2:
+.LunalignedOffby2:
 ;;; CASE 2: The source is unaligned, off by 2
        ldh.ab  r5, [r1, 2]
        sub     r2, r2, 1
@@ -159,7 +159,7 @@ unalignedOffby2:
 #ifdef __BIG_ENDIAN__
        asl.nz  r5, r5, 16
 #endif
-       lpnz    @copy8bytes_2
+       lpnz    @.Lcopy8bytes_2
        ;; LOOP START
        ld.ab   r6, [r1, 4]
        prefetch [r1, 28]       ;Prefetch the next read location
@@ -176,7 +176,7 @@ unalignedOffby2:
 
        st.ab   r7, [r3, 4]
        st.ab   r9, [r3, 4]
-copy8bytes_2:
+.Lcopy8bytes_2:
 
 #ifdef __BIG_ENDIAN__
        lsr.nz  r5, r5, 16
@@ -184,14 +184,14 @@ copy8bytes_2:
        sth.ab  r5, [r3, 2]
 
        and.f   lp_count, r2, 0x07 ;Last 8bytes
-       lpnz    @copybytewise_2
+       lpnz    @.Lcopybytewise_2
        ;; LOOP START
        ldb.ab  r6, [r1,1]
        stb.ab  r6, [r3,1]
-copybytewise_2:
+.Lcopybytewise_2:
        j       [blink]
 
-unalignedOffby3:
+.LunalignedOffby3:
 ;;; CASE 3: The source is unaligned, off by 3
 ;;; Hence, I need to read 1byte for achieve the 32bit alignment
 
@@ -201,7 +201,7 @@ unalignedOffby3:
 #ifdef __BIG_ENDIAN__
        asl.ne  r5, r5, 24
 #endif
-       lpnz    @copy8bytes_3
+       lpnz    @.Lcopy8bytes_3
        ;; LOOP START
        ld.ab   r6, [r1, 4]
        prefetch [r1, 28]       ;Prefetch the next read location
@@ -218,7 +218,7 @@ unalignedOffby3:
 
        st.ab   r7, [r3, 4]
        st.ab   r9, [r3, 4]
-copy8bytes_3:
+.Lcopy8bytes_3:
 
 #ifdef __BIG_ENDIAN__
        lsr.nz  r5, r5, 24
@@ -226,11 +226,11 @@ copy8bytes_3:
        stb.ab  r5, [r3, 1]
 
        and.f   lp_count, r2, 0x07 ;Last 8bytes
-       lpnz    @copybytewise_3
+       lpnz    @.Lcopybytewise_3
        ;; LOOP START
        ldb.ab  r6, [r1,1]
        stb.ab  r6, [r3,1]
-copybytewise_3:
+.Lcopybytewise_3:
        j       [blink]
 
 END(memcpy)
index 0ee7398468476f57b301bde2fa7c7e13735bb3fb..daf2bf52b984c6781dbb6831e22f013b04e58d0d 100644 (file)
@@ -619,10 +619,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
 
                int dirty = !test_and_set_bit(PG_dc_clean, &page->flags);
                if (dirty) {
-                       /* wback + inv dcache lines */
+                       /* wback + inv dcache lines (K-mapping) */
                        __flush_dcache_page(paddr, paddr);
 
-                       /* invalidate any existing icache lines */
+                       /* invalidate any existing icache lines (U-mapping) */
                        if (vma->vm_flags & VM_EXEC)
                                __inv_icache_page(paddr, vaddr);
                }
index 63860adc4814083dd5365d83ffd790fa6d390ab4..f1967eeb32e757bb906580fecfce84a309df9983 100644 (file)
@@ -88,7 +88,7 @@ ex_saved_reg1:
 #ifdef CONFIG_SMP
        sr  r0, [ARC_REG_SCRATCH_DATA0] ; freeup r0 to code with
        GET_CPU_ID  r0                  ; get to per cpu scratch mem,
-       lsl r0, r0, L1_CACHE_SHIFT      ; cache line wide per cpu
+       asl r0, r0, L1_CACHE_SHIFT      ; cache line wide per cpu
        add r0, @ex_saved_reg1, r0
 #else
        st    r0, [@ex_saved_reg1]
@@ -107,7 +107,7 @@ ex_saved_reg1:
 .macro TLBMISS_RESTORE_REGS
 #ifdef CONFIG_SMP
        GET_CPU_ID  r0                  ; get to per cpu scratch mem
-       lsl r0, r0, L1_CACHE_SHIFT      ; each is cache line wide
+       asl r0, r0, L1_CACHE_SHIFT      ; each is cache line wide
        add r0, @ex_saved_reg1, r0
        ld_s  r3, [r0,12]
        ld_s  r2, [r0, 8]
@@ -256,7 +256,7 @@ ex_saved_reg1:
 
 .macro CONV_PTE_TO_TLB
        and    r3, r0, PTE_BITS_RWX     ;          r  w  x
-       lsl    r2, r3, 3                ; Kr Kw Kx 0  0  0 (GLOBAL, kernel only)
+       asl    r2, r3, 3                ; Kr Kw Kx 0  0  0 (GLOBAL, kernel only)
        and.f  0,  r0, _PAGE_GLOBAL
        or.z   r2, r2, r3               ; Kr Kw Kx Ur Uw Ux (!GLOBAL, user page)
 
index dde692812bc16ac70bc3bfba24fc14ba71d158a2..e4fe5145680889edd270edbc4d23655afdedf660 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/init.h>
 #include <asm/mach_desc.h>
-#include <asm/mcip.h>
 
 /*----------------------- Machine Descriptions ------------------------------
  *
index 4e0ad3b827962831fe7d3e0d5a325d33b420381f..0962f2fa3f6e74d3f253593720689cf934dd56b0 100644 (file)
@@ -155,21 +155,21 @@ keyswitch_in {
                        label = "keyswitch_in";
                        gpios = <&pioB 1 GPIO_ACTIVE_HIGH>;
                        linux,code = <28>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                error_in {
                        label = "error_in";
                        gpios = <&pioB 2 GPIO_ACTIVE_HIGH>;
                        linux,code = <29>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                btn {
                        label = "btn";
                        gpios = <&pioC 23 GPIO_ACTIVE_HIGH>;
                        linux,code = <31>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 };
index f89598af4c2b1ef24b1812b15fca28de2c5b4382..6bf873e7d96c226ac532658c62af2ca1e869046a 100644 (file)
@@ -159,7 +159,7 @@ btn {
                        label = "Button";
                        gpios = <&pioC 4 GPIO_ACTIVE_LOW>;
                        linux,code = <0x103>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 };
index bf18ece0c02708c4d7b99ac543e2bc9045daf63b..229e989eb60df3305fb6a609e44e919a3696b143 100644 (file)
@@ -24,15 +24,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <18432000>;
-               };
-
                main_xtal {
                        clock-frequency = <18432000>;
                };
@@ -94,14 +85,14 @@ reset {
                        label = "PB_RST";
                        gpios = <&pioB 30 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                user {
                        label = "PB_USER";
                        gpios = <&pioB 31 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x101>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index f0b1563cb3f164907c63a3ea3d94390a0cd863f9..50a14568f094a64cd5368851e2c39bd250e0cebe 100644 (file)
@@ -171,21 +171,21 @@ prog {
                        label = "PB_PROG";
                        gpios = <&pioE 27 GPIO_ACTIVE_LOW>;
                        linux,code = <0x102>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                reset {
                        label = "PB_RST";
                        gpios = <&pioE 29 GPIO_ACTIVE_LOW>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                user {
                        label = "PB_USER";
                        gpios = <&pioE 31 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x101>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 9f72b49326344925b55d600a1a5c30173c5f7d48..9682d105d4d8317a4733412fbe4cde6241158e74 100644 (file)
@@ -98,14 +98,14 @@ prog {
                        label = "PB_PROG";
                        gpios = <&pioC 17 GPIO_ACTIVE_LOW>;
                        linux,code = <0x102>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                reset {
                        label = "PB_RST";
                        gpios = <&pioC 16 GPIO_ACTIVE_LOW>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index a9aef53ab764202df553a058b73cd77a84c55dff..4f2eebf4a5603a5de81043fdefca99d13400c4cf 100644 (file)
@@ -183,7 +183,7 @@ user_pb {
                        label = "user_pb";
                        gpios = <&pioB 10 GPIO_ACTIVE_LOW>;
                        linux,code = <28>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index e07c2b206beba18c8a139574aa8bc83f74c23545..ad6de73ed5a5fd2f6b1cd7c19e325d60c21537c9 100644 (file)
@@ -45,6 +45,7 @@
 /dts-v1/;
 #include "sama5d2.dtsi"
 #include "sama5d2-pinfunc.h"
+#include <dt-bindings/mfd/atmel-flexcom.h>
 
 / {
        model = "Atmel SAMA5D2 Xplained";
@@ -59,15 +60,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -91,6 +83,22 @@ usb2: ehci@00500000 {
                        status = "okay";
                };
 
+               sdmmc0: sdio-host@a0000000 {
+                       bus-width = <8>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_sdmmc0_default>;
+                       non-removable;
+                       mmc-ddr-1_8v;
+                       status = "okay";
+               };
+
+               sdmmc1: sdio-host@b0000000 {
+                       bus-width = <4>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_sdmmc1_default>;
+                       status = "okay"; /* conflict with qspi0 */
+               };
+
                apb {
                        spi0: spi@f8000000 {
                                pinctrl-names = "default";
@@ -181,12 +189,49 @@ vdd_sdhc_1v8_reg: LDO_REG4 {
                                };
                        };
 
+                       flx0: flexcom@f8034000 {
+                               atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+                               status = "disabled"; /* conflict with ISC_D2 & ISC_D3 data pins */
+
+                               uart5: serial@200 {
+                                       compatible = "atmel,at91sam9260-usart";
+                                       reg = <0x200 0x200>;
+                                       interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>;
+                                       clocks = <&flx0_clk>;
+                                       clock-names = "usart";
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_flx0_default>;
+                                       atmel,fifo-size = <32>;
+                                       status = "okay";
+                               };
+                       };
+
                        uart3: serial@fc008000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_uart3_default>;
                                status = "okay";
                        };
 
+                       flx4: flexcom@fc018000 {
+                               atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+                               status = "okay";
+
+                               i2c2: i2c@600 {
+                                       compatible = "atmel,sama5d2-i2c";
+                                       reg = <0x600 0x200>;
+                                       interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>;
+                                       dmas = <0>, <0>;
+                                       dma-names = "tx", "rx";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       clocks = <&flx4_clk>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_flx4_default>;
+                                       atmel,fifo-size = <16>;
+                                       status = "okay";
+                               };
+                       };
+
                        i2c1: i2c@fc028000 {
                                dmas = <0>, <0>;
                                pinctrl-names = "default";
@@ -201,6 +246,18 @@ at24@54 {
                        };
 
                        pinctrl@fc038000 {
+                               pinctrl_flx0_default: flx0_default {
+                                       pinmux = <PIN_PB28__FLEXCOM0_IO0>,
+                                                <PIN_PB29__FLEXCOM0_IO1>;
+                                       bias-disable;
+                               };
+
+                               pinctrl_flx4_default: flx4_default {
+                                       pinmux = <PIN_PD12__FLEXCOM4_IO0>,
+                                                <PIN_PD13__FLEXCOM4_IO1>;
+                                       bias-disable;
+                               };
+
                                pinctrl_i2c0_default: i2c0_default {
                                        pinmux = <PIN_PD21__TWD0>,
                                                 <PIN_PD22__TWCK0>;
@@ -227,6 +284,46 @@ pinctrl_macb0_default: macb0_default {
                                        bias-disable;
                                };
 
+                               pinctrl_sdmmc0_default: sdmmc0_default {
+                                       cmd_data {
+                                               pinmux = <PIN_PA1__SDMMC0_CMD>,
+                                                        <PIN_PA2__SDMMC0_DAT0>,
+                                                        <PIN_PA3__SDMMC0_DAT1>,
+                                                        <PIN_PA4__SDMMC0_DAT2>,
+                                                        <PIN_PA5__SDMMC0_DAT3>,
+                                                        <PIN_PA6__SDMMC0_DAT4>,
+                                                        <PIN_PA7__SDMMC0_DAT5>,
+                                                        <PIN_PA8__SDMMC0_DAT6>,
+                                                        <PIN_PA9__SDMMC0_DAT7>;
+                                               bias-pull-up;
+                                       };
+
+                                       ck_cd_rstn_vddsel {
+                                               pinmux = <PIN_PA0__SDMMC0_CK>,
+                                                        <PIN_PA10__SDMMC0_RSTN>,
+                                                        <PIN_PA11__SDMMC0_VDDSEL>,
+                                                        <PIN_PA13__SDMMC0_CD>;
+                                               bias-disable;
+                                       };
+                               };
+
+                               pinctrl_sdmmc1_default: sdmmc1_default {
+                                       cmd_data {
+                                               pinmux = <PIN_PA28__SDMMC1_CMD>,
+                                                        <PIN_PA18__SDMMC1_DAT0>,
+                                                        <PIN_PA19__SDMMC1_DAT1>,
+                                                        <PIN_PA20__SDMMC1_DAT2>,
+                                                        <PIN_PA21__SDMMC1_DAT3>;
+                                               bias-pull-up;
+                                       };
+
+                                       conf-ck_cd {
+                                               pinmux = <PIN_PA22__SDMMC1_CK>,
+                                                        <PIN_PA30__SDMMC1_CD>;
+                                               bias-disable;
+                                       };
+                               };
+
                                pinctrl_spi0_default: spi0_default {
                                        pinmux = <PIN_PA14__SPI0_SPCK>,
                                                 <PIN_PA15__SPI0_MOSI>,
index 8488ac53d22d3b4d6f0562ebd9018d3126ce5ee2..ff888d21c786a69b1f56c768ea6a2219056b98dc 100644 (file)
@@ -315,7 +315,7 @@ bp3 {
                        label = "PB_USER";
                        gpios = <&pioE 29 GPIO_ACTIVE_LOW>;
                        linux,code = <0x104>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 45371a1b61b398b6b939292649b20d0315cd399b..131614f28e758653e34cc2b993bb6a5a28f20bbb 100644 (file)
@@ -50,7 +50,6 @@ / {
        compatible = "atmel,sama5d4-xplained", "atmel,sama5d4", "atmel,sama5";
 
        chosen {
-               bootargs = "ignore_loglevel earlyprintk";
                stdout-path = "serial0:115200n8";
        };
 
@@ -59,15 +58,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -235,7 +225,7 @@ pb_user1 {
                        label = "pb_user1";
                        gpios = <&pioE 8 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 6d272c0125e365b64aad7dadbeec309c51c60fc6..2d4a33100af6bdc4fcd4a3500467456673f54325 100644 (file)
@@ -50,7 +50,6 @@ / {
        compatible = "atmel,sama5d4ek", "atmel,sama5d4", "atmel,sama5";
 
        chosen {
-               bootargs = "ignore_loglevel earlyprintk";
                stdout-path = "serial0:115200n8";
        };
 
@@ -59,15 +58,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -304,7 +294,7 @@ pb_user1 {
                        label = "pb_user1";
                        gpios = <&pioE 13 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 8dab4b75ca97cfed9beae29bf49224dc71a06bb9..f90e1c2d3caa2fc41485ba330bdcd691a379e6be 100644 (file)
@@ -21,15 +21,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <18432000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
index 2e92ac020f2383ef58c25a1836b22954834211be..55bd51f07fa601e709f7fc910e7fa757fe4f32ee 100644 (file)
@@ -22,15 +22,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <18432000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -149,7 +140,7 @@ tsc2046@0 {
                                        ti,debounce-tol = /bits/ 16 <65535>;
                                        ti,debounce-max = /bits/ 16 <1>;
 
-                                       linux,wakeup;
+                                       wakeup-source;
                                };
                        };
 
@@ -193,28 +184,28 @@ button_0 {
                        label = "button_0";
                        gpios = <&pioA 27 GPIO_ACTIVE_LOW>;
                        linux,code = <256>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                button_1 {
                        label = "button_1";
                        gpios = <&pioA 26 GPIO_ACTIVE_LOW>;
                        linux,code = <257>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                button_2 {
                        label = "button_2";
                        gpios = <&pioA 25 GPIO_ACTIVE_LOW>;
                        linux,code = <258>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                button_3 {
                        label = "button_3";
                        gpios = <&pioA 24 GPIO_ACTIVE_LOW>;
                        linux,code = <259>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 };
index 23381276ffb8016b0dafc1237eb990bad1e775b1..59df9d73d27659d507d78d195fe3b1be7c499dd4 100644 (file)
@@ -22,15 +22,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <16367660>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -213,14 +204,14 @@ left_click {
                        label = "left_click";
                        gpios = <&pioC 5 GPIO_ACTIVE_LOW>;
                        linux,code = <272>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                right_click {
                        label = "right_click";
                        gpios = <&pioC 4 GPIO_ACTIVE_LOW>;
                        linux,code = <273>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 57548a2c5a1eb80b0701129f612bf3a785b65928..e9cc99b6353ad1e464bb0942c29e3cea6dc5d37e 100644 (file)
@@ -19,15 +19,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <18432000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -206,14 +197,14 @@ btn3 {
                        label = "Button 3";
                        gpios = <&pioA 30 GPIO_ACTIVE_LOW>;
                        linux,code = <0x103>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                btn4 {
                        label = "Button 4";
                        gpios = <&pioA 31 GPIO_ACTIVE_LOW>;
                        linux,code = <0x104>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 9d16ef8453c556f7ad69a21f65d9526a90325115..2400c99134f7f516e97af8234d89b8d3098196bd 100644 (file)
@@ -24,15 +24,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-
                slow_xtal {
                      clock-frequency = <32768>;
                };
@@ -323,14 +314,14 @@ left_click {
                        label = "left_click";
                        gpios = <&pioB 6 GPIO_ACTIVE_LOW>;
                        linux,code = <272>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                right_click {
                        label = "right_click";
                        gpios = <&pioB 7 GPIO_ACTIVE_LOW>;
                        linux,code = <273>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                left {
index acf3451a332da266f9a4e0ad5903a7ec11767587..ca4ddf86817ab64dc6a8a31193191460bfaf8d4b 100644 (file)
@@ -23,15 +23,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <16000000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -219,7 +210,7 @@ enter {
                        label = "Enter";
                        gpios = <&pioB 3 GPIO_ACTIVE_LOW>;
                        linux,code = <28>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 558c9f220bedef3c61ac0b78e3dad2eb76017573..f10566f759cdceba2bedb202365a8c30d979c2f5 100644 (file)
@@ -22,15 +22,6 @@ memory {
        };
 
        clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-
                slow_xtal {
                        clock-frequency = <32768>;
                };
@@ -225,14 +216,14 @@ right_click {
                        label = "right_click";
                        gpios = <&pioB 0 GPIO_ACTIVE_LOW>;
                        linux,code = <273>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                left_click {
                        label = "left_click";
                        gpios = <&pioB 1 GPIO_ACTIVE_LOW>;
                        linux,code = <272>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 26112ebd15fc4e896d576932b330b846fc4cc397..b098ad8cd93a7622b02198ee4bf2b06422af941a 100644 (file)
@@ -12,17 +12,6 @@ memory {
                reg = <0x20000000 0x8000000>;
        };
 
-       clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-       };
-
        clocks {
                slow_xtal {
                        clock-frequency = <32768>;
index bc672fb91466a5635a29c0811c202ef5c418aeeb..fe99231cbde5910bae9f768ead874effd33794c1 100644 (file)
@@ -1459,8 +1459,8 @@ mcasp3: mcasp@48468000 {
                        interrupt-names = "tx", "rx";
                        dmas = <&sdma_xbar 133>, <&sdma_xbar 132>;
                        dma-names = "tx", "rx";
-                       clocks = <&mcasp3_ahclkx_mux>;
-                       clock-names = "fck";
+                       clocks = <&mcasp3_aux_gfclk_mux>, <&mcasp3_ahclkx_mux>;
+                       clock-names = "fck", "ahclkx";
                        status = "disabled";
                };
 
index feb9d34b239c8069450c1d4c1479ebaf207ef3ec..f818ea483aeb57ee804e34d07e4b8383fae2eb63 100644 (file)
@@ -486,7 +486,10 @@ usbotg: usb@10024000 {
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024000 0x200>;
                                interrupts = <56>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 0>;
                                status = "disabled";
                        };
@@ -495,7 +498,10 @@ usbh1: usb@10024200 {
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024200 0x200>;
                                interrupts = <54>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 1>;
                                dr_mode = "host";
                                status = "disabled";
@@ -505,7 +511,10 @@ usbh2: usb@10024400 {
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024400 0x200>;
                                interrupts = <55>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 2>;
                                dr_mode = "host";
                                status = "disabled";
@@ -515,7 +524,6 @@ usbmisc: usbmisc@10024600 {
                                #index-cells = <1>;
                                compatible = "fsl,imx27-usbmisc";
                                reg = <0x10024600 0x200>;
-                               clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
                        };
 
                        sahara2: sahara@10025000 {
index 01aef230773d4052e19ba13b5c4a95df9ea08787..5acbd0dcc2abd9d3ffd3ac09adeab6f2dc33dfad 100644 (file)
@@ -137,7 +137,7 @@ netcp: netcp@26000000 {
        /* NetCP address range */
        ranges = <0 0x26000000 0x1000000>;
 
-       clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+       clocks = <&clkosr>, <&papllclk>, <&clkcpgmac>, <&chipclk12>;
        dma-coherent;
 
        ti,navigator-dmas = <&dma_gbe 0>,
index c56ab6bbfe3c3a1fa1b60f481840cbaa3292a7f2..0e46560551f44b5d5dba4a01dcd74d9eb91ec5b2 100644 (file)
@@ -40,7 +40,7 @@ serial@12100 {
                };
                poweroff@12100 {
                        compatible = "qnap,power-off";
-                       reg = <0x12000 0x100>;
+                       reg = <0x12100 0x100>;
                        clocks = <&gate_clk 7>;
                };
                spi@10600 {
index 8fd8ef2c72dae55de1a1fa6004be38928b6f660f..85f0373df498f07b5b0c54658961bae18b535d7b 100644 (file)
@@ -86,6 +86,10 @@ vcc18_lcd: vcc18-lcd {
        };
 };
 
+&emmc {
+       /delete-property/mmc-hs200-1_8v;
+};
+
 &gpio_keys {
        pinctrl-0 = <&pwr_key_l &ap_lid_int_l &volum_down_l &volum_up_l>;
 
index 6a79c9c526b8809d9ea201d087d680851653e990..04ea209f1737f9fb052f4efc8589e98aa027836e 100644 (file)
@@ -452,8 +452,10 @@ tsadc: tsadc@ff280000 {
                clock-names = "tsadc", "apb_pclk";
                resets = <&cru SRST_TSADC>;
                reset-names = "tsadc-apb";
-               pinctrl-names = "default";
-               pinctrl-0 = <&otp_out>;
+               pinctrl-names = "init", "default", "sleep";
+               pinctrl-0 = <&otp_gpio>;
+               pinctrl-1 = <&otp_out>;
+               pinctrl-2 = <&otp_gpio>;
                #thermal-sensor-cells = <1>;
                rockchip,hw-tshut-temp = <95000>;
                status = "disabled";
@@ -1395,6 +1397,10 @@ uart4_rts: uart4-rts {
                };
 
                tsadc {
+                       otp_gpio: otp-gpio {
+                               rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+
                        otp_out: otp-out {
                                rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>;
                        };
index d9a9aca1ccfdf6d5514b535241d7c5f2ae379e92..e812f5c1bf709db8edded907516c75e66e20c4b8 100644 (file)
@@ -49,7 +49,7 @@ pb_user1 {
                        label = "pb_user1";
                        gpios = <&pioE 27 GPIO_ACTIVE_HIGH>;
                        linux,code = <0x100>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 };
index 15bbaf690047dfb9ab0082d31b83142b63228e09..2193637b9cd2bdb4a14a13e8e48218cc04cadf01 100644 (file)
@@ -1300,7 +1300,7 @@ pit: timer@fc068630 {
                        };
 
                        watchdog@fc068640 {
-                               compatible = "atmel,at91sam9260-wdt";
+                               compatible = "atmel,sama5d4-wdt";
                                reg = <0xfc068640 0x10>;
                                clocks = <&clk32k>;
                                status = "disabled";
index 12edafefd44a3dfb17a5aae66a3fdeb3b8788679..9beea8976584e5067d68ec895c5b9ab1d8eb7929 100644 (file)
@@ -115,7 +115,7 @@ user_pb {
                        label = "user_pb";
                        gpios = <&pioB 10 GPIO_ACTIVE_LOW>;
                        linux,code = <28>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 68c0de36c339f7662b7545e072a60762b82627db..8cc6edb296942762772e5fb4e51cdc99ae219af7 100644 (file)
@@ -143,7 +143,7 @@ user_pb {
                        label = "user_pb";
                        gpios = <&pioB 10 GPIO_ACTIVE_LOW>;
                        linux,code = <28>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index 6736bae43a5b09280ec824146e6caee85f787cdd..0d5acc2cdc8ef93008fc308ac8f3c9c8c1813771 100644 (file)
@@ -158,7 +158,7 @@ dspi0: dspi0@4002c000 {
                                interrupts = <67 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_DSPI0>;
                                clock-names = "dspi";
-                               spi-num-chipselects = <5>;
+                               spi-num-chipselects = <6>;
                                status = "disabled";
                        };
 
@@ -170,7 +170,7 @@ dspi1: dspi1@4002d000 {
                                interrupts = <68 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_DSPI1>;
                                clock-names = "dspi";
-                               spi-num-chipselects = <5>;
+                               spi-num-chipselects = <4>;
                                status = "disabled";
                        };
 
@@ -461,6 +461,8 @@ adc1: adc@400bb000 {
                                clock-names = "adc";
                                #io-channel-cells = <1>;
                                status = "disabled";
+                               fsl,adck-max-frequency = <30000000>, <40000000>,
+                                                       <20000000>;
                        };
 
                        esdhc0: esdhc@400b1000 {
@@ -472,8 +474,6 @@ esdhc0: esdhc@400b1000 {
                                        <&clks VF610_CLK_ESDHC0>;
                                clock-names = "ipg", "ahb", "per";
                                status = "disabled";
-                               fsl,adck-max-frequency = <30000000>, <40000000>,
-                                                       <20000000>;
                        };
 
                        esdhc1: esdhc@400b2000 {
index 1b1e5acd76e2ebd8545f5da91397366b264a989f..e4b1be66b3f56a8d0ecb2590559902bb347b539b 100644 (file)
@@ -125,7 +125,6 @@ CONFIG_POWER_RESET=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_SSB=m
 CONFIG_MFD_ATMEL_HLCDC=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
index a0c57ac88b2756c0a4cdf0b9758e4df65d975833..63f7e6ce649a8630e3f5471a7fea60ee483c5496 100644 (file)
@@ -129,7 +129,6 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_POWER_RESET=y
 # CONFIG_HWMON is not set
-CONFIG_SSB=m
 CONFIG_MFD_ATMEL_FLEXCOM=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
index be1d07d59ee9784c7b3dd12a2150a009c7c742ba..1bd9510de1b9ced64b1947f2734ddbf4c8ce4f5d 100644 (file)
@@ -40,6 +40,11 @@ extern void arch_trigger_all_cpu_backtrace(bool);
 #define arch_trigger_all_cpu_backtrace(x) arch_trigger_all_cpu_backtrace(x)
 #endif
 
+static inline int nr_legacy_irqs(void)
+{
+       return NR_IRQS_LEGACY;
+}
+
 #endif
 
 #endif
index 6551d28c27e687068bc69af093a9a97805362d46..066f7f9ba411e09b5e492a84f03034b86305e38f 100644 (file)
 #include <asm/mach/pci.h>
 
 static int debug_pci;
-static resource_size_t (*align_resource)(struct pci_dev *dev,
-                 const struct resource *res,
-                 resource_size_t start,
-                 resource_size_t size,
-                 resource_size_t align) = NULL;
 
 /*
  * We can't use pci_get_device() here since we are
@@ -461,7 +456,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
                sys->busnr   = busnr;
                sys->swizzle = hw->swizzle;
                sys->map_irq = hw->map_irq;
-               align_resource = hw->align_resource;
                INIT_LIST_HEAD(&sys->resources);
 
                if (hw->private_data)
@@ -470,6 +464,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
                ret = hw->setup(nr, sys);
 
                if (ret > 0) {
+                       struct pci_host_bridge *host_bridge;
+
                        ret = pcibios_init_resources(nr, sys);
                        if (ret)  {
                                kfree(sys);
@@ -491,6 +487,9 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
                        busnr = sys->bus->busn_res.end + 1;
 
                        list_add(&sys->node, head);
+
+                       host_bridge = pci_find_host_bridge(sys->bus);
+                       host_bridge->align_resource = hw->align_resource;
                } else {
                        kfree(sys);
                        if (ret < 0)
@@ -578,14 +577,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 {
        struct pci_dev *dev = data;
        resource_size_t start = res->start;
+       struct pci_host_bridge *host_bridge;
 
        if (res->flags & IORESOURCE_IO && start & 0x300)
                start = (start + 0x3ff) & ~0x3ff;
 
        start = (start + align - 1) & ~(align - 1);
 
-       if (align_resource)
-               return align_resource(dev, res, start, size, align);
+       host_bridge = pci_find_host_bridge(dev->bus);
+
+       if (host_bridge->align_resource)
+               return host_bridge->align_resource(dev, res,
+                               start, size, align);
 
        return start;
 }
index eab83b2435b8b8ed2abc6342e3a22e19da80d623..e06fd299de0846b44b72cd037eacd05b0b2cb051 100644 (file)
@@ -563,18 +563,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                if (vcpu->arch.power_off || vcpu->arch.pause)
                        vcpu_sleep(vcpu);
 
-               /*
-                * Disarming the background timer must be done in a
-                * preemptible context, as this call may sleep.
-                */
-               kvm_timer_flush_hwstate(vcpu);
-
                /*
                 * Preparing the interrupts to be injected also
                 * involves poking the GIC, which must be done in a
                 * non-preemptible context.
                 */
                preempt_disable();
+               kvm_timer_flush_hwstate(vcpu);
                kvm_vgic_flush_hwstate(vcpu);
 
                local_irq_disable();
index 6984342da13d09fd0194563f4b598cfb913ec6c1..7dace909d5cf158c9f7771da8ef7c951ee2dea1c 100644 (file)
@@ -98,6 +98,11 @@ static void kvm_flush_dcache_pud(pud_t pud)
        __kvm_flush_dcache_pud(pud);
 }
 
+static bool kvm_is_device_pfn(unsigned long pfn)
+{
+       return !pfn_valid(pfn);
+}
+
 /**
  * stage2_dissolve_pmd() - clear and flush huge PMD entry
  * @kvm:       pointer to kvm structure.
@@ -213,7 +218,7 @@ static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
                        kvm_tlb_flush_vmid_ipa(kvm, addr);
 
                        /* No need to invalidate the cache for device mappings */
-                       if ((pte_val(old_pte) & PAGE_S2_DEVICE) != PAGE_S2_DEVICE)
+                       if (!kvm_is_device_pfn(__phys_to_pfn(addr)))
                                kvm_flush_dcache_pte(old_pte);
 
                        put_page(virt_to_page(pte));
@@ -305,8 +310,7 @@ static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
 
        pte = pte_offset_kernel(pmd, addr);
        do {
-               if (!pte_none(*pte) &&
-                   (pte_val(*pte) & PAGE_S2_DEVICE) != PAGE_S2_DEVICE)
+               if (!pte_none(*pte) && !kvm_is_device_pfn(__phys_to_pfn(addr)))
                        kvm_flush_dcache_pte(*pte);
        } while (pte++, addr += PAGE_SIZE, addr != end);
 }
@@ -1037,11 +1041,6 @@ static bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
        return kvm_vcpu_dabt_iswrite(vcpu);
 }
 
-static bool kvm_is_device_pfn(unsigned long pfn)
-{
-       return !pfn_valid(pfn);
-}
-
 /**
  * stage2_wp_ptes - write protect PMD range
  * @pmd:       pointer to pmd entry
index 72d622baaad3165ee3e920e6c5fc774e79cf26c5..df1d44bdc375b8c053ca258aa6e6027697e9fc98 100644 (file)
        @ check low interrupts
        ldr     \irqstat, [\base, #IRQ_CAUSE_LOW_OFF]
        ldr     \tmp, [\base, #IRQ_MASK_LOW_OFF]
-       mov     \irqnr, #31
+       mov     \irqnr, #32
        ands    \irqstat, \irqstat, \tmp
 
        @ if no low interrupts set, check high interrupts
        ldreq   \irqstat, [\base, #IRQ_CAUSE_HIGH_OFF]
        ldreq   \tmp, [\base, #IRQ_MASK_HIGH_OFF]
-       moveq   \irqnr, #63
+       moveq   \irqnr, #64
        andeqs  \irqstat, \irqstat, \tmp
 
        @ find first active interrupt source
index 8e7976a4c3e723e1b27a08928700bac2b6cb9a09..cfc696b972f323e07b5e9a180755130e63e5e1b2 100644 (file)
@@ -177,6 +177,7 @@ static struct irq_chip imx_gpc_chip = {
        .irq_unmask             = imx_gpc_irq_unmask,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_set_wake           = imx_gpc_irq_set_wake,
+       .irq_set_type           = irq_chip_set_type_parent,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
 #endif
index 5305ec7341eca5579398a10b72f263a2fbbe8e0e..79e1f876d1c9b9f28dc862e013e7bc657153fd4f 100644 (file)
@@ -143,9 +143,9 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
                 * Ensure that CPU power state is set to ON to avoid CPU
                 * powerdomain transition on wfi
                 */
-               clkdm_wakeup(cpu1_clkdm);
-               omap_set_pwrdm_state(cpu1_pwrdm, PWRDM_POWER_ON);
-               clkdm_allow_idle(cpu1_clkdm);
+               clkdm_wakeup_nolock(cpu1_clkdm);
+               pwrdm_set_next_pwrst(cpu1_pwrdm, PWRDM_POWER_ON);
+               clkdm_allow_idle_nolock(cpu1_clkdm);
 
                if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
                        while (gic_dist_disabled()) {
index cc8a987149e2737db4bf255075d5baf3bc2b2bb0..48495ad82aba16775ff2108ead31ceb820a023b5 100644 (file)
@@ -890,6 +890,36 @@ static int _init_opt_clks(struct omap_hwmod *oh)
        return ret;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
+                                __clk_get_name(oc->_clk));
+                       clk_enable(oc->_clk);
+               }
+}
+
+static void _disable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
+                                __clk_get_name(oc->_clk));
+                       clk_disable(oc->_clk);
+               }
+}
+
 /**
  * _enable_clocks - enable hwmod main clock and interface clocks
  * @oh: struct omap_hwmod *
@@ -917,6 +947,9 @@ static int _enable_clocks(struct omap_hwmod *oh)
                        clk_enable(os->_clk);
        }
 
+       if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
+               _enable_optional_clocks(oh);
+
        /* The opt clocks are controlled by the device driver. */
 
        return 0;
@@ -948,41 +981,14 @@ static int _disable_clocks(struct omap_hwmod *oh)
                        clk_disable(os->_clk);
        }
 
+       if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
+               _disable_optional_clocks(oh);
+
        /* The opt clocks are controlled by the device driver. */
 
        return 0;
 }
 
-static void _enable_optional_clocks(struct omap_hwmod *oh)
-{
-       struct omap_hwmod_opt_clk *oc;
-       int i;
-
-       pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
-
-       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
-               if (oc->_clk) {
-                       pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
-                                __clk_get_name(oc->_clk));
-                       clk_enable(oc->_clk);
-               }
-}
-
-static void _disable_optional_clocks(struct omap_hwmod *oh)
-{
-       struct omap_hwmod_opt_clk *oc;
-       int i;
-
-       pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
-
-       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
-               if (oc->_clk) {
-                       pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
-                                __clk_get_name(oc->_clk));
-                       clk_disable(oc->_clk);
-               }
-}
-
 /**
  * _omap4_enable_module - enable CLKCTRL modulemode on OMAP4
  * @oh: struct omap_hwmod *
index ca6df1a734756fa6640067b9158dc1112e37b2a1..76bce11c85a40c477a5b87aab919d5b8dfded5e8 100644 (file)
@@ -523,6 +523,8 @@ struct omap_hwmod_omap4_prcm {
  * HWMOD_RECONFIG_IO_CHAIN: omap_hwmod code needs to reconfigure wake-up 
  *     events by calling _reconfigure_io_chain() when a device is enabled
  *     or idled.
+ * HWMOD_OPT_CLKS_NEEDED: The optional clocks are needed for the module to
+ *     operate and they need to be handled at the same time as the main_clk.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -538,6 +540,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_FORCE_MSTANDBY                   (1 << 11)
 #define HWMOD_SWSUP_SIDLE_ACT                  (1 << 12)
 #define HWMOD_RECONFIG_IO_CHAIN                        (1 << 13)
+#define HWMOD_OPT_CLKS_NEEDED                  (1 << 14)
 
 /*
  * omap_hwmod._int_flags definitions
index 51d1ecb384bdddb95c1996258de93ee9ba9b85ec..ee4e04434a943ea573210fb2468ba29a36232f07 100644 (file)
@@ -1297,6 +1297,44 @@ static struct omap_hwmod dra7xx_mcspi4_hwmod = {
        .dev_attr       = &mcspi4_dev_attr,
 };
 
+/*
+ * 'mcasp' class
+ *
+ */
+static struct omap_hwmod_class_sysconfig dra7xx_mcasp_sysc = {
+       .sysc_offs      = 0x0004,
+       .sysc_flags     = SYSC_HAS_SIDLEMODE,
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dra7xx_mcasp_hwmod_class = {
+       .name   = "mcasp",
+       .sysc   = &dra7xx_mcasp_sysc,
+};
+
+/* mcasp3 */
+static struct omap_hwmod_opt_clk mcasp3_opt_clks[] = {
+       { .role = "ahclkx", .clk = "mcasp3_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp3_hwmod = {
+       .name           = "mcasp3",
+       .class          = &dra7xx_mcasp_hwmod_class,
+       .clkdm_name     = "l4per2_clkdm",
+       .main_clk       = "mcasp3_aux_gfclk_mux",
+       .flags          = HWMOD_OPT_CLKS_NEEDED,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER2_MCASP3_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER2_MCASP3_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+       .opt_clks       = mcasp3_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcasp3_opt_clks),
+};
+
 /*
  * 'mmc' class
  *
@@ -2566,6 +2604,22 @@ static struct omap_hwmod_ocp_if dra7xx_l3_main_1__hdmi = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> mcasp3 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp3 = {
+       .master         = &dra7xx_l4_per2_hwmod,
+       .slave          = &dra7xx_mcasp3_hwmod,
+       .clk            = "l4_root_clk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> mcasp3 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp3 = {
+       .master         = &dra7xx_l3_main_1_hwmod,
+       .slave          = &dra7xx_mcasp3_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per1 -> elm */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__elm = {
        .master         = &dra7xx_l4_per1_hwmod,
@@ -3308,6 +3362,8 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_wkup__dcan1,
        &dra7xx_l4_per2__dcan2,
        &dra7xx_l4_per2__cpgmac0,
+       &dra7xx_l4_per2__mcasp3,
+       &dra7xx_l3_main_1__mcasp3,
        &dra7xx_gmac__mdio,
        &dra7xx_l4_cfg__dma_system,
        &dra7xx_l3_main_1__dss,
index b1288f56d5095b4ad782e81b0453c9094ec47ac1..6256052893ec7b1453c3d0afb6e392c321040567 100644 (file)
@@ -144,6 +144,7 @@ static struct omap_hwmod dm81xx_l4_ls_hwmod = {
        .name           = "l4_ls",
        .clkdm_name     = "alwon_l3s_clkdm",
        .class          = &l4_hwmod_class,
+       .flags          = HWMOD_NO_IDLEST,
 };
 
 /*
@@ -155,6 +156,7 @@ static struct omap_hwmod dm81xx_l4_hs_hwmod = {
        .name           = "l4_hs",
        .clkdm_name     = "alwon_l3_med_clkdm",
        .class          = &l4_hwmod_class,
+       .flags          = HWMOD_NO_IDLEST,
 };
 
 /* L3 slow -> L4 ls peripheral interface running at 125MHz */
@@ -850,6 +852,7 @@ static struct omap_hwmod dm816x_emac0_hwmod = {
        .name           = "emac0",
        .clkdm_name     = "alwon_ethernet_clkdm",
        .class          = &dm816x_emac_hwmod_class,
+       .flags          = HWMOD_NO_IDLEST,
 };
 
 static struct omap_hwmod_ocp_if dm81xx_l4_hs__emac0 = {
index 1dfe34654c43a353a34ac2cb9b941ff9f951b275..58144779dec4c118aac35f60cab6f0c33a68929a 100644 (file)
@@ -24,9 +24,6 @@
 #include <linux/platform_data/iommu-omap.h>
 #include <linux/platform_data/wkup_m3.h>
 
-#include <asm/siginfo.h>
-#include <asm/signal.h>
-
 #include "common.h"
 #include "common-board-devices.h"
 #include "dss-common.h"
@@ -385,29 +382,6 @@ static void __init omap3_pandora_legacy_init(void)
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#ifdef CONFIG_SOC_TI81XX
-static int fault_fixed_up;
-
-static int t410_abort_handler(unsigned long addr, unsigned int fsr,
-                             struct pt_regs *regs)
-{
-       if ((fsr == 0x406 || fsr == 0xc06) && !fault_fixed_up) {
-               pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n",
-                       addr, fsr);
-               fault_fixed_up = 1;
-               return 0;
-       }
-
-       return 1;
-}
-
-static void __init t410_abort_init(void)
-{
-       hook_fault_code(16 + 6, t410_abort_handler, SIGBUS, BUS_OBJERR,
-                       "imprecise external abort");
-}
-#endif
-
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 static struct iommu_platform_data omap4_iommu_pdata = {
        .reset_name = "mmu_cache",
@@ -536,9 +510,6 @@ static struct pdata_init pdata_quirks[] __initdata = {
        { "openpandora,omap3-pandora-600mhz", omap3_pandora_legacy_init, },
        { "openpandora,omap3-pandora-1ghz", omap3_pandora_legacy_init, },
 #endif
-#ifdef CONFIG_SOC_TI81XX
-       { "hp,t410", t410_abort_init, },
-#endif
 #ifdef CONFIG_SOC_OMAP5
        { "ti,omap5-uevm", omap5_uevm_legacy_init, },
 #endif
index 87b98bf92366f4f816ca4f53a32ecae305930016..2dbd3785ee6f0d00b4c3d88bada28d83c0203b2a 100644 (file)
@@ -301,11 +301,11 @@ static void omap3_pm_idle(void)
        if (omap_irq_pending())
                return;
 
-       trace_cpu_idle(1, smp_processor_id());
+       trace_cpu_idle_rcuidle(1, smp_processor_id());
 
        omap_sram_idle();
 
-       trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
+       trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
 }
 
 #ifdef CONFIG_SUSPEND
index 79eb502a1e64a67a7b716d0b31d7db0903aeab9f..73919a36b5775f1facd9cde91be9ef872ab7e18e 100644 (file)
@@ -21,5 +21,5 @@
        @ find cause bits that are unmasked
        ands    \irqstat, \irqstat, \tmp        @ clear Z flag if any
        clzne   \irqnr, \irqstat                @ calc irqnr
-       rsbne   \irqnr, \irqnr, #31
+       rsbne   \irqnr, \irqnr, #32
        .endm
index 13eba2b26e0aa478e7e26eb541855be091ac68e0..8fbfb10047ec30543b4ccf4c7e6787d9fd5ae5b0 100644 (file)
@@ -344,7 +344,7 @@ void __init palm27x_pwm_init(int bl, int lcd)
 {
        palm_bl_power   = bl;
        palm_lcd_power  = lcd;
-       pwm_add_lookup(palm27x_pwm_lookup, ARRAY_SIZE(palm27x_pwm_lookup));
+       pwm_add_table(palm27x_pwm_lookup, ARRAY_SIZE(palm27x_pwm_lookup));
        platform_device_register(&palm27x_backlight);
 }
 #endif
index aebf6de62468962b9398f6ee299c0539920cbba8..0b5c3876720cc3215949a6cbcf017bdf41f1eec8 100644 (file)
@@ -169,7 +169,7 @@ static inline void palmtc_keys_init(void) {}
 #if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
 static struct pwm_lookup palmtc_pwm_lookup[] = {
        PWM_LOOKUP("pxa25x-pwm.1", 0, "pwm-backlight.0", NULL, PALMTC_PERIOD_NS,
-                  PWM_PERIOD_NORMAL),
+                  PWM_POLARITY_NORMAL),
 };
 
 static struct platform_pwm_backlight_data palmtc_backlight_data = {
index 1d2825cb7a65050bc7b05bed4b200f3e8036349a..5fce87f7f254c2fa4b052c5ab91d11a91e2e3a15 100644 (file)
@@ -19,7 +19,7 @@
 #include "common.h"
 #include "rcar-gen2.h"
 
-static const char *r8a7793_boards_compat_dt[] __initconst = {
+static const char * const r8a7793_boards_compat_dt[] __initconst = {
        "renesas,r8a7793",
        NULL,
 };
index 7fdc5bf24f9b5c05d055f59932b285db4b85d465..446334a25cf5c6f0db61a9c10558e6c1e57b7823 100644 (file)
@@ -13,7 +13,7 @@ config SOC_ZX296702
        select ARM_GLOBAL_TIMER
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
-       select PM_GENERIC_DOMAINS
+       select PM_GENERIC_DOMAINS if PM
        help
          Support for ZTE ZX296702 SoC which is a dual core CortexA9MP
 endif
index 2f4b14cfddb4762e88818464dcd6c57d5eff2a5c..591f9db3bf4048a4d727f195e4e2fb95e4ca06c4 100644 (file)
@@ -1061,7 +1061,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
        }
        build_epilogue(&ctx);
 
-       flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
+       flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));
 
 #if __LINUX_ARM_ARCH__ < 7
        if (ctx.imm_count)
index 851fe11c6069d47a714a87840d6a18a3278d0af8..871f21783866d5fdb1557ec56e5f13b602ba331a 100644 (file)
@@ -27,6 +27,7 @@ config ARM64
        select CPU_PM if (SUSPEND || CPU_IDLE)
        select DCACHE_WORD_ACCESS
        select EDAC_SUPPORT
+       select FRAME_POINTER
        select GENERIC_ALLOCATOR
        select GENERIC_CLOCKEVENTS
        select GENERIC_CLOCKEVENTS_BROADCAST
@@ -48,7 +49,7 @@ config ARM64
        select HAVE_ARCH_AUDITSYSCALL
        select HAVE_ARCH_BITREVERSE
        select HAVE_ARCH_JUMP_LABEL
-       select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP
+       select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
@@ -315,6 +316,27 @@ config ARM64_ERRATUM_832075
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_834220
+       bool "Cortex-A57: 834220: Stage 2 translation fault might be incorrectly reported in presence of a Stage 1 fault"
+       depends on KVM
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 834220 on Cortex-A57 parts up to r1p2.
+
+         Affected Cortex-A57 parts might report a Stage 2 translation
+         fault as the result of a Stage 1 fault for load crossing a
+         page boundary when there is a permission or device memory
+         alignment fault at Stage 1 and a translation fault at Stage 2.
+
+         The workaround is to verify that the Stage 1 translation
+         doesn't generate a fault before handling the Stage 2 fault.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
 config ARM64_ERRATUM_845719
        bool "Cortex-A53: 845719: a load might read incorrect data"
        depends on COMPAT
index c24d6adc0420c78bb0efbf747101c87c0be9e81a..04fb73b973f155b477425ff1841e370f0ba87d41 100644 (file)
@@ -2,10 +2,6 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
-config FRAME_POINTER
-       bool
-       default y
-
 config ARM64_PTDUMP
        bool "Export kernel pagetable layout to userspace via debugfs"
        depends on DEBUG_KERNEL
index 2f71f9cdd39c90be282b09d44bb0e795ab0181c6..bdd7aa358d2a5bc232dc510e789e61939416f700 100644 (file)
@@ -224,3 +224,4 @@ CONFIG_CRYPTO_GHASH_ARM64_CE=y
 CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
 CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
 CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
index ce47792a983dda8b2909609502ef80d54c1215f8..f7bd9bf0bbb398bbb2a355c1b24d1f9c035bacf4 100644 (file)
@@ -237,7 +237,7 @@ EXPORT_SYMBOL(ce_aes_setkey);
 static struct crypto_alg aes_alg = {
        .cra_name               = "aes",
        .cra_driver_name        = "aes-ce",
-       .cra_priority           = 300,
+       .cra_priority           = 250,
        .cra_flags              = CRYPTO_ALG_TYPE_CIPHER,
        .cra_blocksize          = AES_BLOCK_SIZE,
        .cra_ctxsize            = sizeof(struct crypto_aes_ctx),
index 74d0b8eb0799cb6635b999f7afb1c7e7c0a361bf..f61c84f6ba021aa9cd149c8b927680d86f6328b7 100644 (file)
@@ -233,7 +233,7 @@ __CMPXCHG_CASE( ,  ,  mb_8, dmb ish,  , l, "memory")
 #undef __CMPXCHG_CASE
 
 #define __CMPXCHG_DBL(name, mb, rel, cl)                               \
-__LL_SC_INLINE int                                                     \
+__LL_SC_INLINE long                                                    \
 __LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1,              \
                                      unsigned long old2,               \
                                      unsigned long new1,               \
index 1fce7908e6904a43791a385b5df76ef080ebefa2..197e06afbf71947eb505a893e53b73be73543be9 100644 (file)
@@ -387,7 +387,7 @@ __CMPXCHG_CASE(x,  ,  mb_8, al, "memory")
 #define __LL_SC_CMPXCHG_DBL(op)        __LL_SC_CALL(__cmpxchg_double##op)
 
 #define __CMPXCHG_DBL(name, mb, cl...)                                 \
-static inline int __cmpxchg_double##name(unsigned long old1,           \
+static inline long __cmpxchg_double##name(unsigned long old1,          \
                                         unsigned long old2,            \
                                         unsigned long new1,            \
                                         unsigned long new2,            \
index 624f9679f4b0abb3e41da2c7ec23c4a7625196e3..9622eb48f894db3fdb06db5441339babc2a1fdeb 100644 (file)
@@ -64,27 +64,31 @@ do {                                                                        \
 
 #define smp_load_acquire(p)                                            \
 ({                                                                     \
-       typeof(*p) ___p1;                                               \
+       union { typeof(*p) __val; char __c[1]; } __u;                   \
        compiletime_assert_atomic_type(*p);                             \
        switch (sizeof(*p)) {                                           \
        case 1:                                                         \
                asm volatile ("ldarb %w0, %1"                           \
-                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+                       : "=r" (*(__u8 *)__u.__c)                       \
+                       : "Q" (*p) : "memory");                         \
                break;                                                  \
        case 2:                                                         \
                asm volatile ("ldarh %w0, %1"                           \
-                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+                       : "=r" (*(__u16 *)__u.__c)                      \
+                       : "Q" (*p) : "memory");                         \
                break;                                                  \
        case 4:                                                         \
                asm volatile ("ldar %w0, %1"                            \
-                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+                       : "=r" (*(__u32 *)__u.__c)                      \
+                       : "Q" (*p) : "memory");                         \
                break;                                                  \
        case 8:                                                         \
                asm volatile ("ldar %0, %1"                             \
-                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+                       : "=r" (*(__u64 *)__u.__c)                      \
+                       : "Q" (*p) : "memory");                         \
                break;                                                  \
        }                                                               \
-       ___p1;                                                          \
+       __u.__val;                                                      \
 })
 
 #define read_barrier_depends()         do { } while(0)
index 7fbed6919b54041f8fd925f8661a72771e733461..eb8432bb82b8dd698c9bdd5723cc870b36158b25 100644 (file)
@@ -23,7 +23,6 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/ptrace.h>
 
 #define COMPAT_USER_HZ         100
 #ifdef __AARCH64EB__
@@ -234,7 +233,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
        return (u32)(unsigned long)uptr;
 }
 
-#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs()))
+#define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
 
 static inline void __user *arch_compat_alloc_user_space(long len)
 {
index 11d5bb0fdd541052b9cdd49197b2dc90e9ece737..8f271b83f9106c7c9753ce2601d3b59e1ffbdfc5 100644 (file)
@@ -29,8 +29,9 @@
 #define ARM64_HAS_PAN                          4
 #define ARM64_HAS_LSE_ATOMICS                  5
 #define ARM64_WORKAROUND_CAVIUM_23154          6
+#define ARM64_WORKAROUND_834220                        7
 
-#define ARM64_NCAPS                            7
+#define ARM64_NCAPS                            8
 
 #ifndef __ASSEMBLY__
 
@@ -46,8 +47,12 @@ enum ftr_type {
 #define FTR_STRICT     true    /* SANITY check strict matching required */
 #define FTR_NONSTRICT  false   /* SANITY check ignored */
 
+#define FTR_SIGNED     true    /* Value should be treated as signed */
+#define FTR_UNSIGNED   false   /* Value should be treated as unsigned */
+
 struct arm64_ftr_bits {
-       bool            strict;   /* CPU Sanity check: strict matching required ? */
+       bool            sign;   /* Value is signed ? */
+       bool            strict; /* CPU Sanity check: strict matching required ? */
        enum ftr_type   type;
        u8              shift;
        u8              width;
@@ -123,6 +128,18 @@ cpuid_feature_extract_field(u64 features, int field)
        return cpuid_feature_extract_field_width(features, field, 4);
 }
 
+static inline unsigned int __attribute_const__
+cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
+{
+       return (u64)(features << (64 - width - field)) >> (64 - width);
+}
+
+static inline unsigned int __attribute_const__
+cpuid_feature_extract_unsigned_field(u64 features, int field)
+{
+       return cpuid_feature_extract_unsigned_field_width(features, field, 4);
+}
+
 static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
 {
        return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
@@ -130,7 +147,9 @@ static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
 
 static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val)
 {
-       return cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width);
+       return ftrp->sign ?
+               cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width) :
+               cpuid_feature_extract_unsigned_field_width(val, ftrp->shift, ftrp->width);
 }
 
 static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
index 54d0ead41afc656e8b06a0850860b164a8b67eaa..61e08f360e31da1f92a38881cd2cf924d2f03c82 100644 (file)
@@ -18,7 +18,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/acpi.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 
 #include <asm/xen/hypervisor.h>
 
 #define DMA_ERROR_CODE (~(dma_addr_t)0)
-extern struct dma_map_ops *dma_ops;
 extern struct dma_map_ops dummy_dma_ops;
 
 static inline struct dma_map_ops *__generic_dma_ops(struct device *dev)
 {
-       if (unlikely(!dev))
-               return dma_ops;
-       else if (dev->archdata.dma_ops)
+       if (dev && dev->archdata.dma_ops)
                return dev->archdata.dma_ops;
-       else if (acpi_disabled)
-               return dma_ops;
 
        /*
-        * When ACPI is enabled, if arch_set_dma_ops is not called,
-        * we will disable device DMA capability by setting it
-        * to dummy_dma_ops.
+        * We expect no ISA devices, and all other DMA masters are expected to
+        * have someone call arch_setup_dma_ops at device creation time.
         */
        return &dummy_dma_ops;
 }
index e54415ec693571d1d4195d57b1928e2e58173353..9732908bfc8a54b546c4cab40802f70a56b36fce 100644 (file)
@@ -138,16 +138,18 @@ extern struct pmu perf_ops_bp;
 /* Determine number of BRP registers available. */
 static inline int get_num_brps(void)
 {
+       u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1);
        return 1 +
-               cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
+               cpuid_feature_extract_unsigned_field(dfr0,
                                                ID_AA64DFR0_BRPS_SHIFT);
 }
 
 /* Determine number of WRP registers available. */
 static inline int get_num_wrps(void)
 {
+       u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1);
        return 1 +
-               cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
+               cpuid_feature_extract_unsigned_field(dfr0,
                                                ID_AA64DFR0_WRPS_SHIFT);
 }
 
index 23eb450b820ba03ce83b737f308fcd3d6b33f9a8..8e8d30684392b1065b0c5d1f65e7715e4028331c 100644 (file)
@@ -7,4 +7,9 @@ struct pt_regs;
 
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
+static inline int nr_legacy_irqs(void)
+{
+       return 0;
+}
+
 #endif
index 17e92f05b1fe597ea1c4e833debf7541be0fde79..3ca894ecf699b33693e214479ca196bced5fa0c3 100644 (file)
@@ -99,11 +99,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
        *vcpu_cpsr(vcpu) |= COMPAT_PSR_T_BIT;
 }
 
+/*
+ * vcpu_reg should always be passed a register number coming from a
+ * read of ESR_EL2. Otherwise, it may give the wrong result on AArch32
+ * with banked registers.
+ */
 static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
 {
-       if (vcpu_mode_is_32bit(vcpu))
-               return vcpu_reg32(vcpu, reg_num);
-
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
 }
 
index c0e87898ba96b04f2e5b847a0dacf01f4eb1dff1..24165784b8038b732ea568d1e74fd8c0a699b914 100644 (file)
@@ -101,7 +101,7 @@ static inline void cpu_set_default_tcr_t0sz(void)
 #define destroy_context(mm)            do { } while(0)
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
 
-#define init_new_context(tsk,mm)       ({ atomic64_set(&mm->context.id, 0); 0; })
+#define init_new_context(tsk,mm)       ({ atomic64_set(&(mm)->context.id, 0); 0; })
 
 /*
  * This is called when "tsk" is about to enter lazy TLB mode.
index f3acf421ded4f55616abd7b68a7dcf83081e6f38..7e074f93f383fea1891ce79d4048c22f647841a7 100644 (file)
@@ -80,6 +80,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define _PAGE_DEFAULT          (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
 
 #define PAGE_KERNEL            __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
+#define PAGE_KERNEL_RO         __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
+#define PAGE_KERNEL_ROX        __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY)
 #define PAGE_KERNEL_EXEC       __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
 #define PAGE_KERNEL_EXEC_CONT  __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT)
 
index 0cd7b5947dfcfc635c8f6c7de4480f8b015d8fd6..2d4ca4bb0dd34a18ed6bfde2d5fa4e4319402903 100644 (file)
@@ -32,7 +32,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/psci.h>
-#include <asm/types.h>
+#include <linux/types.h>
 #include <asm/ptrace.h>
 
 #define __KVM_HAVE_GUEST_DEBUG
index 24926f2504f7aaf2e37a6f9ecf1692ce3fff422b..feb6b4efa6414846d5598ccb0913a544ba0cf441 100644 (file)
@@ -75,6 +75,15 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                           (1 << MIDR_VARIANT_SHIFT) | 2),
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_834220
+       {
+       /* Cortex-A57 r0p0 - r1p2 */
+               .desc = "ARM erratum 834220",
+               .capability = ARM64_WORKAROUND_834220,
+               MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
+                          (1 << MIDR_VARIANT_SHIFT) | 2),
+       },
+#endif
 #ifdef CONFIG_ARM64_ERRATUM_845719
        {
        /* Cortex-A53 r0p[01234] */
index 52f0d7a5a1c2e0ea0629d51da7204723bd531f66..0669c63281ea01a93ef9794f9731b424b6afd28e 100644 (file)
@@ -44,8 +44,9 @@ unsigned int compat_elf_hwcap2 __read_mostly;
 
 DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 
-#define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
+#define __ARM64_FTR_BITS(SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
        {                                               \
+               .sign = SIGNED,                         \
                .strict = STRICT,                       \
                .type = TYPE,                           \
                .shift = SHIFT,                         \
@@ -53,6 +54,14 @@ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
                .safe_val = SAFE_VAL,                   \
        }
 
+/* Define a feature with signed values */
+#define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
+       __ARM64_FTR_BITS(FTR_SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL)
+
+/* Define a feature with unsigned value */
+#define U_ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
+       __ARM64_FTR_BITS(FTR_UNSIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL)
+
 #define ARM64_FTR_END                                  \
        {                                               \
                .width = 0,                             \
@@ -99,7 +108,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
         * Differing PARange is fine as long as all peripherals and memory are mapped
         * within the minimum PARange of all CPUs
         */
-       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0),
        ARM64_FTR_END,
 };
 
@@ -115,18 +124,18 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
 };
 
 static struct arm64_ftr_bits ftr_ctr[] = {
-       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),        /* RAO */
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),      /* RAO */
        ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0),  /* CWG */
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),   /* ERG */
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1),   /* DminLine */
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0),        /* CWG */
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), /* ERG */
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */
        /*
         * Linux can handle differing I-cache policies. Userspace JITs will
         * make use of *minLine
         */
-       ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0),     /* L1Ip */
+       U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0),   /* L1Ip */
        ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0),        /* RAZ */
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),    /* IminLine */
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),  /* IminLine */
        ARM64_FTR_END,
 };
 
@@ -144,12 +153,12 @@ static struct arm64_ftr_bits ftr_id_mmfr0[] = {
 
 static struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
        ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
-       ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
+       U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
        ARM64_FTR_END,
 };
 
@@ -696,7 +705,7 @@ static void cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
 }
 
 /* Check if we have a particular HWCAP enabled */
-static bool cpus_have_hwcap(const struct arm64_cpu_capabilities *cap)
+static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities *cap)
 {
        bool rc;
 
index 706679d0a0b4227c4a7267cd85142192576d7ab3..212ae6361d8be45d6d73d197284a1ca587599342 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/seq_file.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
+#include <linux/delay.h>
 
 /*
  * In case the boot CPU is hotpluggable, we record its initial state and
@@ -112,6 +113,10 @@ static int c_show(struct seq_file *m, void *v)
                 */
                seq_printf(m, "processor\t: %d\n", i);
 
+               seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+                          loops_per_jiffy / (500000UL/HZ),
+                          loops_per_jiffy / (5000UL/HZ) % 100);
+
                /*
                 * Dump out the common processor features in a single line.
                 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
index de46b50f4cdf952087e77d473314e75728efeec0..4eeb17198cfaf598fd403b1e4040c77f5ee3068a 100644 (file)
@@ -127,7 +127,11 @@ static int __init uefi_init(void)
        table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
        config_tables = early_memremap(efi_to_phys(efi.systab->tables),
                                       table_size);
-
+       if (config_tables == NULL) {
+               pr_warn("Unable to map EFI config table array.\n");
+               retval = -ENOMEM;
+               goto out;
+       }
        retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
                                         sizeof(efi_config_table_64_t), NULL);
 
@@ -209,6 +213,14 @@ void __init efi_init(void)
                         PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
        memmap.phys_map = params.mmap;
        memmap.map = early_memremap(params.mmap, params.mmap_size);
+       if (memmap.map == NULL) {
+               /*
+               * If we are booting via UEFI, the UEFI memory map is the only
+               * description of memory we have, so there is little point in
+               * proceeding if we cannot access it.
+               */
+               panic("Unable to map EFI memory map.\n");
+       }
        memmap.map_end = memmap.map + params.mmap_size;
        memmap.desc_size = params.desc_size;
        memmap.desc_version = params.desc_ver;
@@ -224,8 +236,9 @@ static bool __init efi_virtmap_init(void)
 {
        efi_memory_desc_t *md;
 
+       init_new_context(NULL, &efi_mm);
+
        for_each_efi_memory_desc(&memmap, md) {
-               u64 paddr, npages, size;
                pgprot_t prot;
 
                if (!(md->attribute & EFI_MEMORY_RUNTIME))
@@ -233,11 +246,6 @@ static bool __init efi_virtmap_init(void)
                if (md->virt_addr == 0)
                        return false;
 
-               paddr = md->phys_addr;
-               npages = md->num_pages;
-               memrange_efi_to_native(&paddr, &npages);
-               size = npages << PAGE_SHIFT;
-
                pr_info("  EFI remap 0x%016llx => %p\n",
                        md->phys_addr, (void *)md->virt_addr);
 
@@ -254,7 +262,9 @@ static bool __init efi_virtmap_init(void)
                else
                        prot = PAGE_KERNEL;
 
-               create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot);
+               create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
+                                  md->num_pages << EFI_PAGE_SHIFT, 
+                                  __pgprot(pgprot_val(prot) | PTE_NG));
        }
        return true;
 }
@@ -270,12 +280,12 @@ static int __init arm64_enable_runtime_services(void)
 
        if (!efi_enabled(EFI_BOOT)) {
                pr_info("EFI services will not be available.\n");
-               return -1;
+               return 0;
        }
 
        if (efi_runtime_disabled()) {
                pr_info("EFI runtime services will be disabled.\n");
-               return -1;
+               return 0;
        }
 
        pr_info("Remapping and enabling EFI services.\n");
@@ -285,7 +295,7 @@ static int __init arm64_enable_runtime_services(void)
                                                   mapsize);
        if (!memmap.map) {
                pr_err("Failed to remap EFI memory map\n");
-               return -1;
+               return -ENOMEM;
        }
        memmap.map_end = memmap.map + mapsize;
        efi.memmap = &memmap;
@@ -294,13 +304,13 @@ static int __init arm64_enable_runtime_services(void)
                                                   sizeof(efi_system_table_t));
        if (!efi.systab) {
                pr_err("Failed to remap EFI System Table\n");
-               return -1;
+               return -ENOMEM;
        }
        set_bit(EFI_SYSTEM_TABLES, &efi.flags);
 
        if (!efi_virtmap_init()) {
                pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
-               return -1;
+               return -ENOMEM;
        }
 
        /* Set up runtime services function pointers */
@@ -329,14 +339,7 @@ core_initcall(arm64_dmi_init);
 
 static void efi_set_pgd(struct mm_struct *mm)
 {
-       if (mm == &init_mm)
-               cpu_set_reserved_ttbr0();
-       else
-               cpu_switch_mm(mm->pgd, mm);
-
-       local_flush_tlb_all();
-       if (icache_is_aivivt())
-               __local_flush_icache_all();
+       switch_mm(NULL, mm, NULL);
 }
 
 void efi_virtmap_load(void)
index 2bbdc0e4fd140581706d17b54b8a9089b77e7630..b1adc51b2c2e7682212554ba8276b5e7c25fbff5 100644 (file)
@@ -473,7 +473,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
  * cpu logical map array containing MPIDR values related to logical
  * cpus. Assumes that cpu_logical_map(0) has already been initialized.
  */
-void __init of_parse_and_init_cpus(void)
+static void __init of_parse_and_init_cpus(void)
 {
        struct device_node *dn = NULL;
 
index 40f7b33a22dafce27c3491d181170760916aec04..1095aa483a1c28e5387b23895c14d7a1746268a3 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/ftrace.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
@@ -41,7 +42,7 @@ void notrace __cpu_suspend_save(struct cpu_suspend_ctx *ptr,
  * time the notifier runs debug exceptions might have been enabled already,
  * with HW breakpoints registers content still in an unknown state.
  */
-void (*hw_breakpoint_restore)(void *);
+static void (*hw_breakpoint_restore)(void *);
 void __init cpu_suspend_set_dbg_restorer(void (*hw_bp_restore)(void *))
 {
        /* Prevent multiple restore hook initializations */
@@ -70,6 +71,13 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
         */
        local_dbg_save(flags);
 
+       /*
+        * Function graph tracer state gets incosistent when the kernel
+        * calls functions that never return (aka suspend finishers) hence
+        * disable graph tracing during their execution.
+        */
+       pause_graph_tracing();
+
        /*
         * mm context saved on the stack, it will be restored when
         * the cpu comes out of reset through the identity mapped
@@ -111,6 +119,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
                        hw_breakpoint_restore(NULL);
        }
 
+       unpause_graph_tracing();
+
        /*
         * Restore pstate flags. OS lock and mdscr have been already
         * restored, so from this point onwards, debugging is fully
index f6fe17d88da55d0b212b4d6ffe900f962e1e7bd5..b467fd0a384b36b87fe76ef7e50b4a28bda8bd01 100644 (file)
@@ -15,6 +15,9 @@ ccflags-y := -shared -fno-common -fno-builtin
 ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
                $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
 
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
 # Workaround for bare-metal (ELF) toolchains that neglect to pass -shared
 # down to collect2, resulting in silent corruption of the vDSO image.
 ccflags-y += -Wl,-shared
index 1599701ef044b28b2534a3766dde1d255dba103a..86c289832272d71ba48786414bb6e4ecb9b9cb14 100644 (file)
@@ -864,6 +864,10 @@ ENTRY(__kvm_flush_vm_context)
 ENDPROC(__kvm_flush_vm_context)
 
 __kvm_hyp_panic:
+       // Stash PAR_EL1 before corrupting it in __restore_sysregs
+       mrs     x0, par_el1
+       push    x0, xzr
+
        // Guess the context by looking at VTTBR:
        // If zero, then we're already a host.
        // Otherwise restore a minimal host context before panicing.
@@ -898,7 +902,7 @@ __kvm_hyp_panic:
        mrs     x3, esr_el2
        mrs     x4, far_el2
        mrs     x5, hpfar_el2
-       mrs     x6, par_el1
+       pop     x6, xzr         // active context PAR_EL1
        mrs     x7, tpidr_el2
 
        mov     lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
@@ -914,7 +918,7 @@ __kvm_hyp_panic:
 ENDPROC(__kvm_hyp_panic)
 
 __hyp_panic_str:
-       .ascii  "HYP panic:\nPS:%08x PC:%p ESR:%p\nFAR:%p HPFAR:%p PAR:%p\nVCPU:%p\n\0"
+       .ascii  "HYP panic:\nPS:%08x PC:%016x ESR:%08x\nFAR:%016x HPFAR:%016x PAR:%016x\nVCPU:%p\n\0"
 
        .align  2
 
@@ -1015,9 +1019,15 @@ el1_trap:
        b.ne    1f              // Not an abort we care about
 
        /* This is an abort. Check for permission fault */
+alternative_if_not ARM64_WORKAROUND_834220
        and     x2, x1, #ESR_ELx_FSC_TYPE
        cmp     x2, #FSC_PERM
        b.ne    1f              // Not a permission fault
+alternative_else
+       nop                     // Use the permission fault path to
+       nop                     // check for a valid S1 translation,
+       nop                     // regardless of the ESR value.
+alternative_endif
 
        /*
         * Check for Stage-1 page table walk, which is guaranteed
index 85c57158dcd96a83d80ce99c2c557b371c275984..648112e90ed546d2d052ccf7d9f66866d2390d06 100644 (file)
@@ -48,7 +48,7 @@ static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
 
        /* Note: These now point to the banked copies */
        *vcpu_spsr(vcpu) = new_spsr_value;
-       *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
+       *vcpu_reg32(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
 
        /* Branch to exception vector */
        if (sctlr & (1 << 13))
index f636a2639f031dd03d0b5058ccf378721d67dbf4..e87f53ff5f583aeb47b3ec3187d229df380b2c50 100644 (file)
@@ -76,13 +76,28 @@ static void flush_context(unsigned int cpu)
                __flush_icache_all();
 }
 
-static int is_reserved_asid(u64 asid)
+static bool check_update_reserved_asid(u64 asid, u64 newasid)
 {
        int cpu;
-       for_each_possible_cpu(cpu)
-               if (per_cpu(reserved_asids, cpu) == asid)
-                       return 1;
-       return 0;
+       bool hit = false;
+
+       /*
+        * Iterate over the set of reserved ASIDs looking for a match.
+        * If we find one, then we can update our mm to use newasid
+        * (i.e. the same ASID in the current generation) but we can't
+        * exit the loop early, since we need to ensure that all copies
+        * of the old ASID are updated to reflect the mm. Failure to do
+        * so could result in us missing the reserved ASID in a future
+        * generation.
+        */
+       for_each_possible_cpu(cpu) {
+               if (per_cpu(reserved_asids, cpu) == asid) {
+                       hit = true;
+                       per_cpu(reserved_asids, cpu) = newasid;
+               }
+       }
+
+       return hit;
 }
 
 static u64 new_context(struct mm_struct *mm, unsigned int cpu)
@@ -92,12 +107,14 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
        u64 generation = atomic64_read(&asid_generation);
 
        if (asid != 0) {
+               u64 newasid = generation | (asid & ~ASID_MASK);
+
                /*
                 * If our current ASID was active during a rollover, we
                 * can continue to use it and this was just a false alarm.
                 */
-               if (is_reserved_asid(asid))
-                       return generation | (asid & ~ASID_MASK);
+               if (check_update_reserved_asid(asid, newasid))
+                       return newasid;
 
                /*
                 * We had a valid ASID in a previous life, so try to re-use
@@ -105,7 +122,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                 */
                asid &= ~ASID_MASK;
                if (!__test_and_set_bit(asid, asid_map))
-                       goto bump_gen;
+                       return newasid;
        }
 
        /*
@@ -129,10 +146,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
 set_asid:
        __set_bit(asid, asid_map);
        cur_idx = asid;
-
-bump_gen:
-       asid |= generation;
-       return asid;
+       return asid | generation;
 }
 
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
index 131a199114b405e8403f05137e560a2b317f4941..7963aa4b5d2869b70dfd9a2f3d0ef501a033480b 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/gfp.h>
+#include <linux/acpi.h>
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/genalloc.h>
@@ -28,9 +29,6 @@
 
 #include <asm/cacheflush.h>
 
-struct dma_map_ops *dma_ops;
-EXPORT_SYMBOL(dma_ops);
-
 static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
                                 bool coherent)
 {
@@ -515,13 +513,7 @@ EXPORT_SYMBOL(dummy_dma_ops);
 
 static int __init arm64_dma_init(void)
 {
-       int ret;
-
-       dma_ops = &swiotlb_dma_ops;
-
-       ret = atomic_pool_init();
-
-       return ret;
+       return atomic_pool_init();
 }
 arch_initcall(arm64_dma_init);
 
@@ -552,10 +544,14 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 {
        bool coherent = is_device_dma_coherent(dev);
        int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
+       size_t iosize = size;
        void *addr;
 
        if (WARN(!dev, "cannot create IOMMU mapping for unknown device\n"))
                return NULL;
+
+       size = PAGE_ALIGN(size);
+
        /*
         * Some drivers rely on this, and we probably don't want the
         * possibility of stale kernel data being read by devices anyway.
@@ -566,7 +562,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
                struct page **pages;
                pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
 
-               pages = iommu_dma_alloc(dev, size, gfp, ioprot, handle,
+               pages = iommu_dma_alloc(dev, iosize, gfp, ioprot, handle,
                                        flush_page);
                if (!pages)
                        return NULL;
@@ -574,7 +570,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
                addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot,
                                              __builtin_return_address(0));
                if (!addr)
-                       iommu_dma_free(dev, pages, size, handle);
+                       iommu_dma_free(dev, pages, iosize, handle);
        } else {
                struct page *page;
                /*
@@ -591,7 +587,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
                if (!addr)
                        return NULL;
 
-               *handle = iommu_dma_map_page(dev, page, 0, size, ioprot);
+               *handle = iommu_dma_map_page(dev, page, 0, iosize, ioprot);
                if (iommu_dma_mapping_error(dev, *handle)) {
                        if (coherent)
                                __free_pages(page, get_order(size));
@@ -606,6 +602,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                               dma_addr_t handle, struct dma_attrs *attrs)
 {
+       size_t iosize = size;
+
+       size = PAGE_ALIGN(size);
        /*
         * @cpu_addr will be one of 3 things depending on how it was allocated:
         * - A remapped array of pages from iommu_dma_alloc(), for all
@@ -617,17 +616,17 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
         * Hence how dodgy the below logic looks...
         */
        if (__in_atomic_pool(cpu_addr, size)) {
-               iommu_dma_unmap_page(dev, handle, size, 0, NULL);
+               iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
                __free_from_pool(cpu_addr, size);
        } else if (is_vmalloc_addr(cpu_addr)){
                struct vm_struct *area = find_vm_area(cpu_addr);
 
                if (WARN_ON(!area || !area->pages))
                        return;
-               iommu_dma_free(dev, area->pages, size, &handle);
+               iommu_dma_free(dev, area->pages, iosize, &handle);
                dma_common_free_remap(cpu_addr, size, VM_USERMAP);
        } else {
-               iommu_dma_unmap_page(dev, handle, size, 0, NULL);
+               iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
                __free_pages(virt_to_page(cpu_addr), get_order(size));
        }
 }
@@ -984,8 +983,8 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                        struct iommu_ops *iommu, bool coherent)
 {
-       if (!acpi_disabled && !dev->archdata.dma_ops)
-               dev->archdata.dma_ops = dma_ops;
+       if (!dev->archdata.dma_ops)
+               dev->archdata.dma_ops = &swiotlb_dma_ops;
 
        dev->archdata.dma_coherent = coherent;
        __iommu_setup_dma_ops(dev, dma_base, size, iommu);
index 19211c4a891111cee301552a234821646f522ea6..92ddac1e8ca2f35b8f24028514bb761aed3591a4 100644 (file)
@@ -393,16 +393,16 @@ static struct fault_info {
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 1 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 2 translation fault"     },
        { do_page_fault,        SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"     },
-       { do_bad,               SIGBUS,  0,             "reserved access flag fault"    },
+       { do_bad,               SIGBUS,  0,             "unknown 8"                     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 1 access flag fault"     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 2 access flag fault"     },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 3 access flag fault"     },
-       { do_bad,               SIGBUS,  0,             "reserved permission fault"     },
+       { do_bad,               SIGBUS,  0,             "unknown 12"                    },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 1 permission fault"      },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 2 permission fault"      },
        { do_page_fault,        SIGSEGV, SEGV_ACCERR,   "level 3 permission fault"      },
        { do_bad,               SIGBUS,  0,             "synchronous external abort"    },
-       { do_bad,               SIGBUS,  0,             "asynchronous external abort"   },
+       { do_bad,               SIGBUS,  0,             "unknown 17"                    },
        { do_bad,               SIGBUS,  0,             "unknown 18"                    },
        { do_bad,               SIGBUS,  0,             "unknown 19"                    },
        { do_bad,               SIGBUS,  0,             "synchronous abort (translation table walk)" },
@@ -410,16 +410,16 @@ static struct fault_info {
        { do_bad,               SIGBUS,  0,             "synchronous abort (translation table walk)" },
        { do_bad,               SIGBUS,  0,             "synchronous abort (translation table walk)" },
        { do_bad,               SIGBUS,  0,             "synchronous parity error"      },
-       { do_bad,               SIGBUS,  0,             "asynchronous parity error"     },
+       { do_bad,               SIGBUS,  0,             "unknown 25"                    },
        { do_bad,               SIGBUS,  0,             "unknown 26"                    },
        { do_bad,               SIGBUS,  0,             "unknown 27"                    },
-       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk" },
-       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk" },
-       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk" },
-       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk" },
+       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
+       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
+       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
+       { do_bad,               SIGBUS,  0,             "synchronous parity error (translation table walk)" },
        { do_bad,               SIGBUS,  0,             "unknown 32"                    },
        { do_bad,               SIGBUS,  BUS_ADRALN,    "alignment fault"               },
-       { do_bad,               SIGBUS,  0,             "debug event"                   },
+       { do_bad,               SIGBUS,  0,             "unknown 34"                    },
        { do_bad,               SIGBUS,  0,             "unknown 35"                    },
        { do_bad,               SIGBUS,  0,             "unknown 36"                    },
        { do_bad,               SIGBUS,  0,             "unknown 37"                    },
@@ -433,21 +433,21 @@ static struct fault_info {
        { do_bad,               SIGBUS,  0,             "unknown 45"                    },
        { do_bad,               SIGBUS,  0,             "unknown 46"                    },
        { do_bad,               SIGBUS,  0,             "unknown 47"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 48"                    },
+       { do_bad,               SIGBUS,  0,             "TLB conflict abort"            },
        { do_bad,               SIGBUS,  0,             "unknown 49"                    },
        { do_bad,               SIGBUS,  0,             "unknown 50"                    },
        { do_bad,               SIGBUS,  0,             "unknown 51"                    },
        { do_bad,               SIGBUS,  0,             "implementation fault (lockdown abort)" },
-       { do_bad,               SIGBUS,  0,             "unknown 53"                    },
+       { do_bad,               SIGBUS,  0,             "implementation fault (unsupported exclusive)" },
        { do_bad,               SIGBUS,  0,             "unknown 54"                    },
        { do_bad,               SIGBUS,  0,             "unknown 55"                    },
        { do_bad,               SIGBUS,  0,             "unknown 56"                    },
        { do_bad,               SIGBUS,  0,             "unknown 57"                    },
-       { do_bad,               SIGBUS,  0,             "implementation fault (coprocessor abort)" },
+       { do_bad,               SIGBUS,  0,             "unknown 58"                    },
        { do_bad,               SIGBUS,  0,             "unknown 59"                    },
        { do_bad,               SIGBUS,  0,             "unknown 60"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 61"                    },
-       { do_bad,               SIGBUS,  0,             "unknown 62"                    },
+       { do_bad,               SIGBUS,  0,             "section domain fault"          },
+       { do_bad,               SIGBUS,  0,             "page domain fault"             },
        { do_bad,               SIGBUS,  0,             "unknown 63"                    },
 };
 
index c2fa6b56613c23ba111c94310df522454e2ea732..873e363048c6c661eda620bbd4f826ba568c5ba7 100644 (file)
@@ -64,8 +64,12 @@ EXPORT_SYMBOL(phys_mem_access_prot);
 
 static void __init *early_alloc(unsigned long sz)
 {
-       void *ptr = __va(memblock_alloc(sz, sz));
-       BUG_ON(!ptr);
+       phys_addr_t phys;
+       void *ptr;
+
+       phys = memblock_alloc(sz, sz);
+       BUG_ON(!phys);
+       ptr = __va(phys);
        memset(ptr, 0, sz);
        return ptr;
 }
@@ -81,55 +85,19 @@ static void split_pmd(pmd_t *pmd, pte_t *pte)
        do {
                /*
                 * Need to have the least restrictive permissions available
-                * permissions will be fixed up later. Default the new page
-                * range as contiguous ptes.
+                * permissions will be fixed up later
                 */
-               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC_CONT));
+               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
                pfn++;
        } while (pte++, i++, i < PTRS_PER_PTE);
 }
 
-/*
- * Given a PTE with the CONT bit set, determine where the CONT range
- * starts, and clear the entire range of PTE CONT bits.
- */
-static void clear_cont_pte_range(pte_t *pte, unsigned long addr)
-{
-       int i;
-
-       pte -= CONT_RANGE_OFFSET(addr);
-       for (i = 0; i < CONT_PTES; i++) {
-               set_pte(pte, pte_mknoncont(*pte));
-               pte++;
-       }
-       flush_tlb_all();
-}
-
-/*
- * Given a range of PTEs set the pfn and provided page protection flags
- */
-static void __populate_init_pte(pte_t *pte, unsigned long addr,
-                               unsigned long end, phys_addr_t phys,
-                               pgprot_t prot)
-{
-       unsigned long pfn = __phys_to_pfn(phys);
-
-       do {
-               /* clear all the bits except the pfn, then apply the prot */
-               set_pte(pte, pfn_pte(pfn, prot));
-               pte++;
-               pfn++;
-               addr += PAGE_SIZE;
-       } while (addr != end);
-}
-
 static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
-                                 unsigned long end, phys_addr_t phys,
+                                 unsigned long end, unsigned long pfn,
                                  pgprot_t prot,
                                  void *(*alloc)(unsigned long size))
 {
        pte_t *pte;
-       unsigned long next;
 
        if (pmd_none(*pmd) || pmd_sect(*pmd)) {
                pte = alloc(PTRS_PER_PTE * sizeof(pte_t));
@@ -142,30 +110,12 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 
        pte = pte_offset_kernel(pmd, addr);
        do {
-               next = min(end, (addr + CONT_SIZE) & CONT_MASK);
-               if (((addr | next | phys) & ~CONT_MASK) == 0) {
-                       /* a block of CONT_PTES  */
-                       __populate_init_pte(pte, addr, next, phys,
-                                           prot | __pgprot(PTE_CONT));
-               } else {
-                       /*
-                        * If the range being split is already inside of a
-                        * contiguous range but this PTE isn't going to be
-                        * contiguous, then we want to unmark the adjacent
-                        * ranges, then update the portion of the range we
-                        * are interrested in.
-                        */
-                        clear_cont_pte_range(pte, addr);
-                        __populate_init_pte(pte, addr, next, phys, prot);
-               }
-
-               pte += (next - addr) >> PAGE_SHIFT;
-               phys += next - addr;
-               addr = next;
-       } while (addr != end);
+               set_pte(pte, pfn_pte(pfn, prot));
+               pfn++;
+       } while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-void split_pud(pud_t *old_pud, pmd_t *pmd)
+static void split_pud(pud_t *old_pud, pmd_t *pmd)
 {
        unsigned long addr = pud_pfn(*old_pud) << PAGE_SHIFT;
        pgprot_t prot = __pgprot(pud_val(*old_pud) ^ addr);
@@ -223,7 +173,8 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
                                }
                        }
                } else {
-                       alloc_init_pte(pmd, addr, next, phys, prot, alloc);
+                       alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
+                                      prot, alloc);
                }
                phys += next - addr;
        } while (pmd++, addr = next, addr != end);
@@ -362,8 +313,8 @@ static void __init __map_memblock(phys_addr_t start, phys_addr_t end)
         * for now. This will get more fine grained later once all memory
         * is mapped
         */
-       unsigned long kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
-       unsigned long kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
+       unsigned long kernel_x_start = round_down(__pa(_stext), SWAPPER_BLOCK_SIZE);
+       unsigned long kernel_x_end = round_up(__pa(__init_end), SWAPPER_BLOCK_SIZE);
 
        if (end < kernel_x_start) {
                create_mapping(start, __phys_to_virt(start),
@@ -447,22 +398,22 @@ static void __init map_mem(void)
        memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
 }
 
-void __init fixup_executable(void)
+static void __init fixup_executable(void)
 {
 #ifdef CONFIG_DEBUG_RODATA
        /* now that we are actually fully mapped, make the start/end more fine grained */
-       if (!IS_ALIGNED((unsigned long)_stext, SECTION_SIZE)) {
+       if (!IS_ALIGNED((unsigned long)_stext, SWAPPER_BLOCK_SIZE)) {
                unsigned long aligned_start = round_down(__pa(_stext),
-                                                       SECTION_SIZE);
+                                                        SWAPPER_BLOCK_SIZE);
 
                create_mapping(aligned_start, __phys_to_virt(aligned_start),
                                __pa(_stext) - aligned_start,
                                PAGE_KERNEL);
        }
 
-       if (!IS_ALIGNED((unsigned long)__init_end, SECTION_SIZE)) {
+       if (!IS_ALIGNED((unsigned long)__init_end, SWAPPER_BLOCK_SIZE)) {
                unsigned long aligned_end = round_up(__pa(__init_end),
-                                                       SECTION_SIZE);
+                                                         SWAPPER_BLOCK_SIZE);
                create_mapping(__pa(__init_end), (unsigned long)__init_end,
                                aligned_end - __pa(__init_end),
                                PAGE_KERNEL);
@@ -475,7 +426,7 @@ void mark_rodata_ro(void)
 {
        create_mapping_late(__pa(_stext), (unsigned long)_stext,
                                (unsigned long)_etext - (unsigned long)_stext,
-                               PAGE_KERNEL_EXEC | PTE_RDONLY);
+                               PAGE_KERNEL_ROX);
 
 }
 #endif
@@ -691,7 +642,7 @@ void __set_fixmap(enum fixed_addresses idx,
 void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
 {
        const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
-       pgprot_t prot = PAGE_KERNEL | PTE_RDONLY;
+       pgprot_t prot = PAGE_KERNEL_RO;
        int size, offset;
        void *dt_virt;
 
index 98a26ce82d266f164021a9a7d93b2694bad7641d..aee5637ea436f2b5333af25c1db408790a6e0ac5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com>
+ * Copyright (C) 2014-2015 Zi Shen Lim <zlim.lnx@gmail.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
@@ -35,6 +35,7 @@
        aarch64_insn_gen_comp_branch_imm(0, offset, Rt, A64_VARIANT(sf), \
                AARCH64_INSN_BRANCH_COMP_##type)
 #define A64_CBZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, ZERO)
+#define A64_CBNZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, NONZERO)
 
 /* Conditional branch (immediate) */
 #define A64_COND_BRANCH(cond, offset) \
index a44e5293c6f58adb288e9c0d0549fcbe26c98daa..d6a53ef2350be81a090c07ab7d6df409d99c6a37 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com>
+ * Copyright (C) 2014-2015 Zi Shen Lim <zlim.lnx@gmail.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
@@ -50,7 +50,7 @@ static const int bpf2a64[] = {
        [BPF_REG_8] = A64_R(21),
        [BPF_REG_9] = A64_R(22),
        /* read-only frame pointer to access stack */
-       [BPF_REG_FP] = A64_FP,
+       [BPF_REG_FP] = A64_R(25),
        /* temporary register for internal BPF JIT */
        [TMP_REG_1] = A64_R(23),
        [TMP_REG_2] = A64_R(24),
@@ -155,18 +155,49 @@ static void build_prologue(struct jit_ctx *ctx)
        stack_size += 4; /* extra for skb_copy_bits buffer */
        stack_size = STACK_ALIGN(stack_size);
 
+       /*
+        * BPF prog stack layout
+        *
+        *                         high
+        * original A64_SP =>   0:+-----+ BPF prologue
+        *                        |FP/LR|
+        * current A64_FP =>  -16:+-----+
+        *                        | ... | callee saved registers
+        *                        +-----+
+        *                        |     | x25/x26
+        * BPF fp register => -80:+-----+
+        *                        |     |
+        *                        | ... | BPF prog stack
+        *                        |     |
+        *                        |     |
+        * current A64_SP =>      +-----+
+        *                        |     |
+        *                        | ... | Function call stack
+        *                        |     |
+        *                        +-----+
+        *                          low
+        *
+        */
+
+       /* Save FP and LR registers to stay align with ARM64 AAPCS */
+       emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
+       emit(A64_MOV(1, A64_FP, A64_SP), ctx);
+
        /* Save callee-saved register */
        emit(A64_PUSH(r6, r7, A64_SP), ctx);
        emit(A64_PUSH(r8, r9, A64_SP), ctx);
        if (ctx->tmp_used)
                emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);
 
-       /* Set up BPF stack */
-       emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
+       /* Save fp (x25) and x26. SP requires 16 bytes alignment */
+       emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx);
 
-       /* Set up frame pointer */
+       /* Set up BPF prog stack base register (x25) */
        emit(A64_MOV(1, fp, A64_SP), ctx);
 
+       /* Set up function call stack */
+       emit(A64_SUB_I(1, A64_SP, A64_SP, stack_size), ctx);
+
        /* Clear registers A and X */
        emit_a64_mov_i64(ra, 0, ctx);
        emit_a64_mov_i64(rx, 0, ctx);
@@ -190,14 +221,17 @@ static void build_epilogue(struct jit_ctx *ctx)
        /* We're done with BPF stack */
        emit(A64_ADD_I(1, A64_SP, A64_SP, stack_size), ctx);
 
+       /* Restore fs (x25) and x26 */
+       emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
+
        /* Restore callee-saved register */
        if (ctx->tmp_used)
                emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
        emit(A64_POP(r8, r9, A64_SP), ctx);
        emit(A64_POP(r6, r7, A64_SP), ctx);
 
-       /* Restore frame pointer */
-       emit(A64_MOV(1, fp, A64_SP), ctx);
+       /* Restore FP/LR registers */
+       emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
 
        /* Set return value */
        emit(A64_MOV(1, A64_R(0), r0), ctx);
@@ -225,6 +259,17 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        u8 jmp_cond;
        s32 jmp_offset;
 
+#define check_imm(bits, imm) do {                              \
+       if ((((imm) > 0) && ((imm) >> (bits))) ||               \
+           (((imm) < 0) && (~(imm) >> (bits)))) {              \
+               pr_info("[%2d] imm=%d(0x%x) out of range\n",    \
+                       i, imm, imm);                           \
+               return -EINVAL;                                 \
+       }                                                       \
+} while (0)
+#define check_imm19(imm) check_imm(19, imm)
+#define check_imm26(imm) check_imm(26, imm)
+
        switch (code) {
        /* dst = src */
        case BPF_ALU | BPF_MOV | BPF_X:
@@ -258,15 +303,33 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                break;
        case BPF_ALU | BPF_DIV | BPF_X:
        case BPF_ALU64 | BPF_DIV | BPF_X:
-               emit(A64_UDIV(is64, dst, dst, src), ctx);
-               break;
        case BPF_ALU | BPF_MOD | BPF_X:
        case BPF_ALU64 | BPF_MOD | BPF_X:
-               ctx->tmp_used = 1;
-               emit(A64_UDIV(is64, tmp, dst, src), ctx);
-               emit(A64_MUL(is64, tmp, tmp, src), ctx);
-               emit(A64_SUB(is64, dst, dst, tmp), ctx);
+       {
+               const u8 r0 = bpf2a64[BPF_REG_0];
+
+               /* if (src == 0) return 0 */
+               jmp_offset = 3; /* skip ahead to else path */
+               check_imm19(jmp_offset);
+               emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+               emit(A64_MOVZ(1, r0, 0, 0), ctx);
+               jmp_offset = epilogue_offset(ctx);
+               check_imm26(jmp_offset);
+               emit(A64_B(jmp_offset), ctx);
+               /* else */
+               switch (BPF_OP(code)) {
+               case BPF_DIV:
+                       emit(A64_UDIV(is64, dst, dst, src), ctx);
+                       break;
+               case BPF_MOD:
+                       ctx->tmp_used = 1;
+                       emit(A64_UDIV(is64, tmp, dst, src), ctx);
+                       emit(A64_MUL(is64, tmp, tmp, src), ctx);
+                       emit(A64_SUB(is64, dst, dst, tmp), ctx);
+                       break;
+               }
                break;
+       }
        case BPF_ALU | BPF_LSH | BPF_X:
        case BPF_ALU64 | BPF_LSH | BPF_X:
                emit(A64_LSLV(is64, dst, dst, src), ctx);
@@ -393,17 +456,6 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                emit(A64_ASR(is64, dst, dst, imm), ctx);
                break;
 
-#define check_imm(bits, imm) do {                              \
-       if ((((imm) > 0) && ((imm) >> (bits))) ||               \
-           (((imm) < 0) && (~(imm) >> (bits)))) {              \
-               pr_info("[%2d] imm=%d(0x%x) out of range\n",    \
-                       i, imm, imm);                           \
-               return -EINVAL;                                 \
-       }                                                       \
-} while (0)
-#define check_imm19(imm) check_imm(19, imm)
-#define check_imm26(imm) check_imm(26, imm)
-
        /* JUMP off */
        case BPF_JMP | BPF_JA:
                jmp_offset = bpf2a64_offset(i + off, i, ctx);
@@ -740,7 +792,7 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
        if (bpf_jit_enable > 1)
                bpf_jit_dump(prog->len, image_size, 2, ctx.image);
 
-       bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
+       bpf_flush_icache(header, ctx.image + ctx.idx);
 
        set_memory_ro((unsigned long)header, header->pages);
        prog->bpf_func = (void *)ctx.image;
index db589167838c01051ecbf6cf1c0289b6fbc60546..dd3ac75776ad982973d0ae2f5f2ccd0e58a53c7e 100644 (file)
@@ -16,6 +16,7 @@ config H8300
        select OF_EARLY_FLATTREE
        select HAVE_MEMBLOCK
        select HAVE_DMA_ATTRS
+       select CLKSRC_OF
 
 config RWSEM_GENERIC_SPINLOCK
        def_bool y
index 0d2d96e52d9fed374928fdd0be0466aca66827f1..e1c02ca230cb0a9dbd985b59b0646eb86f0d9891 100644 (file)
@@ -22,7 +22,9 @@ KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
 KBUILD_AFLAGS += $(aflags-y)
 LDFLAGS += $(ldflags-y)
 
+ifeq ($(CROSS_COMPILE),)
 CROSS_COMPILE := h8300-unknown-linux-
+endif
 
 core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
 ifneq '$(CONFIG_H8300_BUILTIN_DTB)' '""'
index 87d03b7ee97eeca9300544026bc62a4e6c04562f..d7bc3fa7f2c6b6b58ff35a5d97f1087d1d2c0b65 100644 (file)
@@ -14,11 +14,12 @@ OBJECTS = $(obj)/head.o $(obj)/misc.o
 # in order to suppress error message.
 #
 CONFIG_MEMORY_START     ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
+CONFIG_BOOT_LINK_OFFSET ?= 0x00280000
 IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET))))
 
 LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup -T $(obj)/vmlinux.lds \
+       --defsym output=$(CONFIG_MEMORY_START)
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
        $(call if_changed,ld)
index 74c0d8cc40ba8ec8ef65717ca4eb8c9da8be514d..0436350c1df5813950ef04905581a9b07993e8aa 100644 (file)
@@ -9,8 +9,8 @@
        .section        .text..startup,"ax"
        .global startup
 startup:
+       mov.l   #startup, sp
        mov.l   er0, er4
-       mov.l   er0, sp
        mov.l   #__sbss, er0
        mov.l   #__ebss, er1
        sub.l   er0, er1
@@ -24,7 +24,7 @@ startup:
        bne     1b
        jsr     @decompress_kernel
        mov.l   er4, er0
-       jmp     @0x400000
+       jmp     @output
 
        .align  9
 fake_headers_as_bzImage:
index c4f2cfcb117bd6a6b9f1844c3a3313fa5e6be94a..6029c53518951a1253b498d77e1b4d963b9d36b9 100644 (file)
@@ -28,7 +28,7 @@ static unsigned long free_mem_end_ptr;
 
 extern char input_data[];
 extern int input_len;
-static unsigned char *output;
+extern char output[];
 
 #define HEAP_SIZE             0x10000
 
@@ -56,15 +56,10 @@ void *memcpy(void *dest, const void *src, size_t n)
 
 static void error(char *x)
 {
-
        while (1)
                ;       /* Halt */
 }
 
-#define STACK_SIZE (4096)
-long user_stack[STACK_SIZE];
-long *stack_start = &user_stack[STACK_SIZE];
-
 void decompress_kernel(void)
 {
        free_mem_ptr = (unsigned long)&_end;
index a0a3a0ed54ef17450ae9dbe7f7a38e0789098fdd..44fd209db88a69b60b885464d8d36a4f5d9a3f47 100644 (file)
@@ -27,6 +27,6 @@ SECTIONS
                 *(.bss*)
         . = ALIGN(0x4) ;
         __ebss = . ;
-        __end = . ;
         }
+        _end = . ;
 }
index dfb5c102f8dad0c4a60065d1bfa6d6d2e5dd20ae..4ce9fa874a577e559d5e916a24ddfb71eef6fcdd 100644 (file)
@@ -7,7 +7,7 @@ / {
 
        chosen {
                bootargs = "console=ttySC2,38400";
-               stdout-path = <&sci2>;
+               stdout-path = &sci2;
        };
        aliases {
                serial0 = &sci0;
@@ -25,13 +25,13 @@ pllclk: pllclk {
                compatible = "renesas,h8s2678-pll-clock";
                clocks = <&xclk>;
                #clock-cells = <0>;
-               reg = <0xfee03b 2>, <0xfee045 2>;
+               reg = <0xffff3b 1>, <0xffff45 1>;
        };
        core_clk: core_clk {
                compatible = "renesas,h8300-div-clock";
                clocks = <&pllclk>;
                #clock-cells = <0>;
-               reg = <0xfee03b 2>;
+               reg = <0xffff3b 1>;
                renesas,width = <3>;
        };
        fclk: fclk {
index 1d09b2f2e0fefd9625cd7e39f92e5e40dce2152f..bb837cded268446bbd67d7610daf374807d502bb 100644 (file)
@@ -36,20 +36,20 @@ static inline void ctrl_outl(unsigned long b, unsigned long addr)
        *(volatile unsigned long *)addr = b;
 }
 
-static inline void ctrl_bclr(int b, unsigned long addr)
+static inline void ctrl_bclr(int b, unsigned char *addr)
 {
        if (__builtin_constant_p(b))
-               __asm__("bclr %1,%0" : : "WU"(addr), "i"(b));
+               __asm__("bclr %1,%0" : "+WU"(*addr): "i"(b));
        else
-               __asm__("bclr %w1,%0" : : "WU"(addr), "r"(b));
+               __asm__("bclr %w1,%0" : "+WU"(*addr): "r"(b));
 }
 
-static inline void ctrl_bset(int b, unsigned long addr)
+static inline void ctrl_bset(int b, unsigned char *addr)
 {
        if (__builtin_constant_p(b))
-               __asm__("bset %1,%0" : : "WU"(addr), "i"(b));
+               __asm__("bset %1,%0" : "+WU"(*addr): "i"(b));
        else
-               __asm__("bset %w1,%0" : : "WU"(addr), "r"(b));
+               __asm__("bset %w1,%0" : "+WU"(*addr): "r"(b));
 }
 
 #endif /* __KERNEL__ */
index 544c30785ad4b81ced562cc7624430c22d99403b..b408fe660cf8ceab685de783220a2db991b4dfc3 100644 (file)
 
 #ifdef __KERNEL__
 
+/*
+ * Size of kernel stack for each process. This must be a power of 2...
+ */
+#define THREAD_SIZE_ORDER      1
+#define THREAD_SIZE            8192    /* 2 pages */
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -46,14 +52,6 @@ struct thread_info {
 #define init_thread_info       (init_thread_union.thread_info)
 #define init_stack             (init_thread_union.stack)
 
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#define THREAD_SIZE_ORDER      1
-#define THREAD_SIZE            8192    /* 2 pages */
-
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
index 0fd1fe65c0b8bc9710d6aed34a852f4f91618272..c772abe6d19ce0d4ff06f12c8d5fb004905c26c5 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/clk-provider.h>
 #include <linux/memblock.h>
 #include <linux/screen_info.h>
+#include <linux/clocksource.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -252,4 +253,5 @@ void __init calibrate_delay(void)
 void __init time_init(void)
 {
        of_clk_init(NULL);
+       clocksource_probe();
 }
index 7c302dcf52494b51dabd50dd9dd31f8bb7e8b918..cb5dfb02c88d412cd67b33827da834a3770d0c7f 100644 (file)
@@ -1,5 +1,6 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 
 #define ROMTOP 0x000000
 #define RAMTOP 0x400000
@@ -42,11 +43,10 @@ SECTIONS
        . = RAMTOP;
        _ramstart = .;
 #define ADDR(x) ROMEND
-#else
 #endif
        _sdata = . ;
        __data_start = . ;
-       RW_DATA_SECTION(0,0,0)
+       RW_DATA_SECTION(0, PAGE_SIZE, THREAD_SIZE)
 #if defined(CONFIG_ROMKERNEL)
 #undef ADDR
 #endif
index dd295335891a03dc2cfbb657883135749f38083e..5c3f688a5232f2690007a8e92a12ba76ae11b4a5 100644 (file)
@@ -17,6 +17,7 @@ obj- := $(platform-)
 obj-y += kernel/
 obj-y += mm/
 obj-y += net/
+obj-y += vdso/
 
 ifdef CONFIG_KVM
 obj-y += kvm/
index a424e46b50afaa85f5e081f5f9ee8e31887816bb..a96c81d1d22e6afce0973161639024e93346fd0b 100644 (file)
@@ -33,6 +33,7 @@ platforms += sibyte
 platforms += sni
 platforms += txx9
 platforms += vr41xx
+platforms += xilfpga
 
 # include the platform specific files
 include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
index e3aa5b0b4ef17771fbd2afa1557f29ee6a7a2b3d..71683a8533723866872de04f7194d07a28f33045 100644 (file)
@@ -5,6 +5,7 @@ config MIPS
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
+       select ARCH_USE_BUILTIN_BSWAP
        select HAVE_CONTEXT_TRACKING
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IDE
@@ -60,6 +61,8 @@ config MIPS
        select SYSCTL_EXCEPTION_TRACE
        select HAVE_VIRT_CPU_ACCOUNTING_GEN
        select HAVE_IRQ_TIME_ACCOUNTING
+       select GENERIC_TIME_VSYSCALL
+       select ARCH_CLOCKSOURCE_DATA
 
 menu "Machine selection"
 
@@ -401,6 +404,28 @@ config MACH_PISTACHIO
        help
          This enables support for the IMG Pistachio SoC platform.
 
+config MACH_XILFPGA
+       bool "MIPSfpga Xilinx based boards"
+       select ARCH_REQUIRE_GPIOLIB
+       select BOOT_ELF32
+       select BOOT_RAW
+       select BUILTIN_DTB
+       select CEVT_R4K
+       select COMMON_CLK
+       select CSRC_R4K
+       select IRQ_MIPS_CPU
+       select LIBFDT
+       select MIPS_CPU_SCACHE
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_ZBOOT_UART16550
+       select USE_OF
+       select USE_GENERIC_EARLY_PRINTK_8250
+       help
+         This enables support for the IMG University Program MIPSfpga platform.
+
 config MIPS_MALTA
        bool "MIPS Malta board"
        select ARCH_MAY_HAVE_PC_FDC
@@ -424,6 +449,7 @@ config MIPS_MALTA
        select MIPS_L1_CACHE_SHIFT_6
        select PCI_GT64XXX_PCI0
        select MIPS_MSC
+       select SMP_UP if SMP
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
@@ -449,6 +475,8 @@ config MIPS_MALTA
        select SYS_SUPPORTS_ZBOOT
        select USE_OF
        select ZONE_DMA32 if 64BIT
+       select BUILTIN_DTB
+       select LIBFDT
        help
          This enables support for the MIPS Technologies Malta evaluation
          board.
@@ -964,6 +992,7 @@ source "arch/mips/loongson32/Kconfig"
 source "arch/mips/loongson64/Kconfig"
 source "arch/mips/netlogic/Kconfig"
 source "arch/mips/paravirt/Kconfig"
+source "arch/mips/xilfpga/Kconfig"
 
 endmenu
 
@@ -1036,6 +1065,9 @@ config CSRC_R4K
 config CSRC_SB1250
        bool
 
+config MIPS_CLOCK_VSYSCALL
+       def_bool CSRC_R4K || CLKSRC_MIPS_GIC
+
 config GPIO_TXX9
        select ARCH_REQUIRE_GPIOLIB
        bool
@@ -2529,6 +2561,9 @@ choice
        help
         Allows the configuration of the timer frequency.
 
+       config HZ_24
+               bool "24 HZ" if SYS_SUPPORTS_24HZ || SYS_SUPPORTS_ARBIT_HZ
+
        config HZ_48
                bool "48 HZ" if SYS_SUPPORTS_48HZ || SYS_SUPPORTS_ARBIT_HZ
 
@@ -2552,6 +2587,9 @@ choice
 
 endchoice
 
+config SYS_SUPPORTS_24HZ
+       bool
+
 config SYS_SUPPORTS_48HZ
        bool
 
@@ -2575,13 +2613,18 @@ config SYS_SUPPORTS_1024HZ
 
 config SYS_SUPPORTS_ARBIT_HZ
        bool
-       default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \
-                    !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \
-                    !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \
+       default y if !SYS_SUPPORTS_24HZ && \
+                    !SYS_SUPPORTS_48HZ && \
+                    !SYS_SUPPORTS_100HZ && \
+                    !SYS_SUPPORTS_128HZ && \
+                    !SYS_SUPPORTS_250HZ && \
+                    !SYS_SUPPORTS_256HZ && \
+                    !SYS_SUPPORTS_1000HZ && \
                     !SYS_SUPPORTS_1024HZ
 
 config HZ
        int
+       default 24 if HZ_24
        default 48 if HZ_48
        default 100 if HZ_100
        default 128 if HZ_128
@@ -2685,7 +2728,7 @@ config BUILTIN_DTB
        bool
 
 choice
-       prompt "Kernel appended dtb support" if OF
+       prompt "Kernel appended dtb support" if USE_OF
        default MIPS_NO_APPENDED_DTB
 
        config MIPS_NO_APPENDED_DTB
@@ -2693,6 +2736,20 @@ choice
                help
                  Do not enable appended dtb support.
 
+       config MIPS_ELF_APPENDED_DTB
+               bool "vmlinux"
+               help
+                 With this option, the boot code will look for a device tree binary
+                 DTB) included in the vmlinux ELF section .appended_dtb. By default
+                 it is empty and the DTB can be appended using binutils command
+                 objcopy:
+
+                   objcopy --update-section .appended_dtb=<filename>.dtb vmlinux
+
+                 This is meant as a backward compatiblity convenience for those
+                 systems with a bootloader that can't be upgraded to accommodate
+                 the documented boot protocol using a device tree.
+
        config MIPS_RAW_APPENDED_DTB
                bool "vmlinux.bin"
                help
@@ -2729,6 +2786,25 @@ choice
                  if you don't intend to always append a DTB.
 endchoice
 
+choice
+       prompt "Kernel command line type" if !CMDLINE_OVERRIDE
+       default MIPS_CMDLINE_FROM_DTB if USE_OF && !ATH79 && !MACH_INGENIC && \
+                                        !MIPS_MALTA && !MIPS_SEAD3 && \
+                                        !CAVIUM_OCTEON_SOC
+       default MIPS_CMDLINE_FROM_BOOTLOADER
+
+       config MIPS_CMDLINE_FROM_DTB
+               depends on USE_OF
+               bool "Dtb kernel arguments if available"
+
+       config MIPS_CMDLINE_DTB_EXTEND
+               depends on USE_OF
+               bool "Extend dtb kernel arguments with bootloader arguments"
+
+       config MIPS_CMDLINE_FROM_BOOTLOADER
+               bool "Bootloader kernel arguments if available"
+endchoice
+
 endmenu
 
 config LOCKDEP_SUPPORT
@@ -2739,6 +2815,10 @@ config STACKTRACE_SUPPORT
        bool
        default y
 
+config HAVE_LATENCYTOP_SUPPORT
+       bool
+       default y
+
 config PGTABLE_LEVELS
        int
        default 3 if 64BIT && !PAGE_SIZE_64KB
index e250524021aca8ec7e1b79bfd0b4f088d96f109d..f0e314ceb8baa84d36ea6664772f71df46ad003f 100644 (file)
@@ -113,4 +113,76 @@ config SPINLOCK_TEST
        help
          Add several files to the debugfs to test spinlock speed.
 
+if CPU_MIPSR6
+
+choice
+       prompt "Compact branch policy"
+       default MIPS_COMPACT_BRANCHES_OPTIMAL
+
+config MIPS_COMPACT_BRANCHES_NEVER
+       bool "Never (force delay slot branches)"
+       help
+         Pass the -mcompact-branches=never flag to the compiler in order to
+         force it to always emit branches with delay slots, and make no use
+         of the compact branch instructions introduced by MIPSr6. This is
+         useful if you suspect there may be an issue with compact branches in
+         either the compiler or the CPU.
+
+config MIPS_COMPACT_BRANCHES_OPTIMAL
+       bool "Optimal (use where beneficial)"
+       help
+         Pass the -mcompact-branches=optimal flag to the compiler in order for
+         it to make use of compact branch instructions where it deems them
+         beneficial, and use branches with delay slots elsewhere. This is the
+         default compiler behaviour, and should be used unless you have a
+         reason to choose otherwise.
+
+config MIPS_COMPACT_BRANCHES_ALWAYS
+       bool "Always (force compact branches)"
+       help
+         Pass the -mcompact-branches=always flag to the compiler in order to
+         force it to always emit compact branches, making no use of branch
+         instructions with delay slots. This can result in more compact code
+         which may be beneficial in some scenarios.
+
+endchoice
+
+endif # CPU_MIPSR6
+
+config SCACHE_DEBUGFS
+       bool "L2 cache debugfs entries"
+       depends on DEBUG_FS
+       help
+         Enable this to allow parts of the L2 cache configuration, such as
+         whether or not prefetching is enabled, to be exposed to userland
+         via debugfs.
+
+         If unsure, say N.
+
+menuconfig MIPS_CPS_NS16550
+       bool "CPS SMP NS16550 UART output"
+       depends on MIPS_CPS
+       help
+         Output debug information via an ns16550 compatible UART if exceptions
+         occur early in the boot process of a secondary core.
+
+if MIPS_CPS_NS16550
+
+config MIPS_CPS_NS16550_BASE
+       hex "UART Base Address"
+       default 0x1b0003f8 if MIPS_MALTA
+       help
+         The base address of the ns16550 compatible UART on which to output
+         debug information from the early stages of core startup.
+
+config MIPS_CPS_NS16550_SHIFT
+       int "UART Register Shift"
+       default 0 if MIPS_MALTA
+       help
+         The number of bits to shift ns16550 register indices by in order to
+         form their addresses. That is, log base 2 of the span between
+         adjacent ns16550 registers in the system.
+
+endif # MIPS_CPS_NS16550
+
 endmenu
index 252e347958f383354a597323078512846f592d52..3f70ba54ae21e909973ad9913eb71151fcc50492 100644 (file)
@@ -204,6 +204,10 @@ toolchain-msa                              := $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(
 cflags-$(toolchain-msa)                        += -DTOOLCHAIN_SUPPORTS_MSA
 endif
 
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER)   += -mcompact-branches=never
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL) += -mcompact-branches=optimal
+cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_ALWAYS)  += -mcompact-branches=always
+
 #
 # Firmware support
 #
index 1ba21204ebe021ee164a9f8f4828dd3f3c836f84..8755d618e116ec32fd6fff90d0081b0bb2e4bb9c 100644 (file)
@@ -216,9 +216,9 @@ void __init plat_mem_setup(void)
                                           AR71XX_RESET_SIZE);
        ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
                                         AR71XX_PLL_SIZE);
+       ath79_detect_sys_type();
        ath79_ddr_ctrl_init();
 
-       ath79_detect_sys_type();
        if (mips_machtype != ATH79_MACH_GENERIC_OF)
                detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
 
@@ -281,3 +281,8 @@ MIPS_MACHINE(ATH79_MACH_GENERIC,
             "Generic",
             "Generic AR71XX/AR724X/AR913X based board",
             ath79_generic_init);
+
+MIPS_MACHINE(ATH79_MACH_GENERIC_OF,
+            "DTB",
+            "Generic AR71XX/AR724X/AR913X based board (DT)",
+            NULL);
index 17503a05938e6c3848e950acd366361fd768ab0d..6d38948f0f1ed4a95f29d883cd7fb4abe65ed327 100644 (file)
@@ -105,11 +105,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                  struct ssb_init_invariants *iv)
 {
        char buf[20];
+       int len, err;
 
        /* Fill boardinfo structure */
        memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo));
 
-       bcm47xx_fill_ssb_boardinfo(&iv->boardinfo, NULL);
+       len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
+       if (len > 0) {
+               err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
+               if (err)
+                       pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
+                               buf);
+       }
+       if (!iv->boardinfo.vendor)
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+
+       len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+       if (len > 0) {
+               err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
+               if (err)
+                       pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
+                               buf);
+       }
 
        memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
        bcm47xx_fill_sprom(&iv->sprom, NULL, false);
index 2d5c7a7f24bb943669d7c43fb66bee1482ff6412..a7e569c7968ea7e8bc1a1ce3e629fc54cc2710ee 100644 (file)
@@ -60,9 +60,9 @@ static int get_nvram_var(const char *prefix, const char *postfix,
 }
 
 #define NVRAM_READ_VAL(type)                                           \
-static void nvram_read_ ## type (const char *prefix,                   \
-                                const char *postfix, const char *name, \
-                                type *val, type allset, bool fallback) \
+static void nvram_read_ ## type(const char *prefix,                    \
+                               const char *postfix, const char *name,  \
+                               type *val, type allset, bool fallback)  \
 {                                                                      \
        char buf[100];                                                  \
        int err;                                                        \
@@ -422,7 +422,10 @@ static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-               struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+               struct ssb_sprom_core_pwr_info *pwr_info;
+
+               pwr_info = &sprom->core_pwr_info[i];
+
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u8(prefix, postfix, "maxp2ga",
                              &pwr_info->maxpwr_2g, 0, fallback);
@@ -470,7 +473,10 @@ static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-               struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
+               struct ssb_sprom_core_pwr_info *pwr_info;
+
+               pwr_info = &sprom->core_pwr_info[i];
+
                snprintf(postfix, sizeof(postfix), "%i", i);
                nvram_read_u16(prefix, postfix, "pa2gw3a",
                               &pwr_info->pa_2g[3], 0, fallback);
@@ -535,10 +541,11 @@ static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
        nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
 
        /* The address prefix 00:90:4C is used by Broadcom in their initial
-          configuration. When a mac address with the prefix 00:90:4C is used
-          all devices from the same series are sharing the same mac address.
-          To prevent mac address collisions we replace them with a mac address
-          based on the base address. */
+        * configuration. When a mac address with the prefix 00:90:4C is used
+        * all devices from the same series are sharing the same mac address.
+        * To prevent mac address collisions we replace them with a mac address
+        * based on the base address.
+        */
        if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
                u8 mac[6];
 
@@ -592,32 +599,23 @@ void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
        bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
 }
 
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
-                               const char *prefix)
-{
-       nvram_read_u16(prefix, NULL, "boardvendor", &boardinfo->vendor, 0,
-                      true);
-       if (!boardinfo->vendor)
-               boardinfo->vendor = SSB_BOARDVENDOR_BCM;
-
-       nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
-}
-#endif
-
 #if defined(CONFIG_BCM47XX_SSB)
 static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
 {
        char prefix[10];
 
-       if (bus->bustype == SSB_BUSTYPE_PCI) {
+       switch (bus->bustype) {
+       case SSB_BUSTYPE_SSB:
+               bcm47xx_fill_sprom(out, NULL, false);
+               return 0;
+       case SSB_BUSTYPE_PCI:
                memset(out, 0, sizeof(struct ssb_sprom));
                snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
                         bus->host_pci->bus->number + 1,
                         PCI_SLOT(bus->host_pci->devfn));
                bcm47xx_fill_sprom(out, prefix, false);
                return 0;
-       } else {
+       default:
                pr_warn("Unable to fill SPROM for given bustype.\n");
                return -EINVAL;
        }
index 33727e7f0c79f756a004dc4d5fd964b31b3d6058..b2097c0d2ed78b554ab321c6620767d3ccd29f71 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -31,7 +33,6 @@
 
 #include <uapi/linux/bcm933xx_hcs.h>
 
-#define PFX    "board_bcm963xx: "
 
 #define HCS_OFFSET_128K                        0x20000
 
@@ -740,7 +741,7 @@ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
                memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom));
                return 0;
        } else {
-               printk(KERN_ERR PFX "unable to fill SPROM for given bustype.\n");
+               pr_err("unable to fill SPROM for given bustype\n");
                return -EINVAL;
        }
 }
@@ -784,7 +785,7 @@ void __init board_prom_init(void)
                         cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
        else
                strcpy(cfe_version, "unknown");
-       printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+       pr_info("CFE version: %s\n", cfe_version);
 
        bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
 
@@ -808,8 +809,7 @@ void __init board_prom_init(void)
                char name[17];
                memcpy(name, board_name, 16);
                name[16] = 0;
-               printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
-                      name);
+               pr_err("unknown bcm963xx board: %s\n", name);
                return;
        }
 
@@ -854,7 +854,7 @@ void __init board_setup(void)
 {
        if (!board.name[0])
                panic("unable to detect bcm963xx board");
-       printk(KERN_INFO PFX "board name: %s\n", board.name);
+       pr_info("board name: %s\n", board.name);
 
        /* make sure we're running on expected cpu */
        if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
@@ -910,7 +910,7 @@ int __init board_register_devices(void)
                memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
                if (ssb_arch_register_fallback_sprom(
                                &bcm63xx_get_fallback_sprom) < 0)
-                       pr_err(PFX "failed to register fallback SPROM\n");
+                       pr_err("failed to register fallback SPROM\n");
        }
 #endif
 
index 307ec8b8e41c1eb12129844c9744ed9dd9441fb7..1c7c3fbfa1f330afae049d30e48b731cd6b46499 100644 (file)
@@ -376,10 +376,10 @@ void __init bcm63xx_cpu_init(void)
        bcm63xx_cpu_freq = detect_cpu_clock();
        bcm63xx_memory_size = detect_memory_size();
 
-       printk(KERN_INFO "Detected Broadcom 0x%04x CPU revision %02x\n",
-              bcm63xx_cpu_id, bcm63xx_cpu_rev);
-       printk(KERN_INFO "CPU frequency is %u MHz\n",
-              bcm63xx_cpu_freq / 1000000);
-       printk(KERN_INFO "%uMB of RAM installed\n",
-              bcm63xx_memory_size >> 20);
+       pr_info("Detected Broadcom 0x%04x CPU revision %02x\n",
+               bcm63xx_cpu_id, bcm63xx_cpu_rev);
+       pr_info("CPU frequency is %u MHz\n",
+               bcm63xx_cpu_freq / 1000000);
+       pr_info("%uMB of RAM installed\n",
+               bcm63xx_memory_size >> 20);
 }
index a551bab5ecb94b2aafce31787cea8e6bb31dbd10..9496cd23695149d992e254e7ad2830d9d9860719 100644 (file)
@@ -139,6 +139,6 @@ int __init bcm63xx_pcmcia_register(void)
        return platform_device_register(&bcm63xx_pcmcia_device);
 
 out_err:
-       printk(KERN_ERR "unable to set pcmcia chip select\n");
+       pr_err("unable to set pcmcia chip select\n");
        return ret;
 }
index 1a47ec2a09062b59bf76b1b4de9270435698b88e..c96139097ae270c9fbf6252d086611159bd6503d 100644 (file)
@@ -311,7 +311,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d,
                break;
 
        default:
-               printk(KERN_ERR "bogus flow type combination given !\n");
+               pr_err("bogus flow type combination given !\n");
                return -EINVAL;
        }
 
index 240fb4ffa55c8625ef26354e29cff25c58f63b68..2be9caaa208530757af7ab41eaa6104c9a0616da 100644 (file)
@@ -24,7 +24,7 @@
 
 void bcm63xx_machine_halt(void)
 {
-       printk(KERN_INFO "System halted\n");
+       pr_info("System halted\n");
        while (1)
                ;
 }
@@ -34,7 +34,7 @@ static void bcm6348_a1_reboot(void)
        u32 reg;
 
        /* soft reset all blocks */
-       printk(KERN_INFO "soft-resetting all blocks ...\n");
+       pr_info("soft-resetting all blocks ...\n");
        reg = bcm_perf_readl(PERF_SOFTRESET_REG);
        reg &= ~SOFTRESET_6348_ALL;
        bcm_perf_writel(reg, PERF_SOFTRESET_REG);
@@ -46,7 +46,7 @@ static void bcm6348_a1_reboot(void)
        mdelay(10);
 
        /* Jump to the power on address. */
-       printk(KERN_INFO "jumping to reset vector.\n");
+       pr_info("jumping to reset vector.\n");
        /* set high vectors (base at 0xbfc00000 */
        set_c0_status(ST0_BEV | ST0_ERL);
        /* run uncached in kseg0 */
@@ -110,7 +110,7 @@ void bcm63xx_machine_reboot(void)
        if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() == 0xa1))
                bcm6348_a1_reboot();
 
-       printk(KERN_INFO "triggering watchdog soft-reset...\n");
+       pr_info("triggering watchdog soft-reset...\n");
        if (BCMCPU_IS_6328()) {
                bcm_wdt_writel(1, WDT_SOFTRESET_REG);
        } else {
index 5f11359815688d5350a56cce5704971e4e533b1a..2110359c00e5cb79cf1b04b21c73c83e81f79ea8 100644 (file)
@@ -195,7 +195,7 @@ int bcm63xx_timer_init(void)
        irq = bcm63xx_get_irq_number(IRQ_TIMER);
        ret = request_irq(irq, timer_interrupt, 0, "bcm63xx_timer", NULL);
        if (ret) {
-               printk(KERN_ERR "bcm63xx_timer: failed to register irq\n");
+               pr_err("%s: failed to register irq\n", __func__);
                return ret;
        }
 
index 526ec2789bb9ef0ba208079d307f9580c408c7ec..5b16d2955fbb864afae0103753bd8d0d115eba0e 100644 (file)
@@ -157,7 +157,6 @@ void __init plat_mem_setup(void)
                panic("no dtb found");
 
        __dt_setup_arch(dtb);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
        for (q = bmips_quirk_list; q->quirk_fn; q++) {
                if (of_flat_dt_is_compatible(of_get_flat_dt_root(),
index bac7b8dab9a4907db6733da6e66a6a85fe89a92d..a0bf516ec3948827acbc526c6ebac5a7827e1a22 100644 (file)
@@ -6,6 +6,7 @@ dts-dirs        += mti
 dts-dirs       += netlogic
 dts-dirs       += qca
 dts-dirs       += ralink
+dts-dirs       += xilfpga
 
 obj-y          := $(addsuffix /, $(dts-dirs))
 
index d817bb46b934fd1cb81388dd0d492f55c74171ed..d4bf52cfcf170ee8ac84daa874495e0a6420e542 100644 (file)
@@ -87,14 +87,32 @@ upg_irq0_intc: upg_irq0_intc@406780 {
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406780 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0xf000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <59>;
+                       interrupts = <59>, <57>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <60>, <58>, <62>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
@@ -144,6 +162,56 @@ uart2: serial@406980 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@406380 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406380 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
+               bsce: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bsce";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
@@ -246,5 +314,47 @@ ohci3: usb@490600 {
                        interrupts = <76>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <40>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 277a90adc1a78cb07834dd7c870ac374cc1557da..8e2501694d03fbd93827aeda79ef22f7cfd5d094 100644 (file)
@@ -81,14 +81,32 @@ upg_irq0_intc: upg_irq0_intc@406600 {
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
@@ -138,6 +156,46 @@ uart2: serial@406880 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
index 9e1e571ba346ad7a240faf5a18a54b3f108e3cc7..7e5f76040fb898b19a4bbc301c8a20f3b9368aa4 100644 (file)
@@ -81,14 +81,32 @@ upg_irq0_intc: upg_irq0_intc@406600 {
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
@@ -138,6 +156,46 @@ uart2: serial@406880 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscc: i2c@406300 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406300 0x58>;
+                     interrupts = <26>;
+                     interrupt-names = "upg_bscc";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
index 6e65db86fc618471df11f543b2569872d36f85b4..c739ea77acb0dfe17363ec52cf390cace407e54c 100644 (file)
@@ -87,14 +87,32 @@ upg_irq0_intc: upg_irq0_intc@406600 {
                        compatible = "brcm,bcm7120-l2-intc";
                        reg = <0x406600 0x8>;
 
-                       brcm,int-map-mask = <0x44>;
+                       brcm,int-map-mask = <0x44>, <0x7000000>;
                        brcm,int-fwd-mask = <0x70000>;
 
                        interrupt-controller;
                        #interrupt-cells = <1>;
 
                        interrupt-parent = <&periph_intc>;
-                       interrupts = <56>;
+                       interrupts = <56>, <54>;
+                       interrupt-names = "upg_main", "upg_bsc";
+               };
+
+               upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       reg = <0x408b80 0x8>;
+
+                       brcm,int-map-mask = <0x40>, <0x8000000>, <0x100000>;
+                       brcm,int-fwd-mask = <0>;
+                       brcm,irq-can-wake;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <57>, <55>, <59>;
+                       interrupt-names = "upg_main_aon", "upg_bsc_aon",
+                                         "upg_spi";
                };
 
                sun_top_ctrl: syscon@404000 {
@@ -144,6 +162,36 @@ uart2: serial@406880 {
                        status = "disabled";
                };
 
+               bsca: i2c@406200 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406200 0x58>;
+                     interrupts = <24>;
+                     interrupt-names = "upg_bsca";
+                     status = "disabled";
+               };
+
+               bscb: i2c@406280 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_irq0_intc>;
+                     reg = <0x406280 0x58>;
+                     interrupts = <25>;
+                     interrupt-names = "upg_bscb";
+                     status = "disabled";
+               };
+
+               bscd: i2c@408980 {
+                     clock-frequency = <390000>;
+                     compatible = "brcm,brcmstb-i2c";
+                     interrupt-parent = <&upg_aon_irq0_intc>;
+                     reg = <0x408980 0x58>;
+                     interrupts = <27>;
+                     interrupt-names = "upg_bscd";
+                     status = "disabled";
+               };
+
                enet0: ethernet@430000 {
                        phy-mode = "internal";
                        phy-handle = <&phy1>;
@@ -189,5 +237,47 @@ ohci0: usb@480400 {
                        interrupts = <66>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <86>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 5b660b617eaddb799d04ad6f2e86f15fd767e17e..e24d41ab4e30f9163605180d78605fc02a477db6 100644 (file)
@@ -221,5 +221,47 @@ ohci3: usb@490600 {
                        interrupts = <73>;
                        status = "disabled";
                };
+
+               sata: sata@181000 {
+                       compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+                       reg-names = "ahci", "top-ctrl";
+                       reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+                       interrupt-parent = <&periph_intc>;
+                       interrupts = <40>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       brcm,broken-ncq;
+                       brcm,broken-phy;
+                       status = "disabled";
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy0>;
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy1>;
+                       };
+               };
+
+               sata_phy: sata-phy@1800000 {
+                       compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+                       reg = <0x180100 0x0eff>;
+                       reg-names = "phy";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       sata_phy0: sata-phy@0 {
+                               reg = <0>;
+                               #phy-cells = <0>;
+                       };
+
+                       sata_phy1: sata-phy@1 {
+                               reg = <1>;
+                               #phy-cells = <0>;
+                       };
+               };
        };
 };
index 3fe0445b9d37bae86ed53564b09747bd321653dd..d3d28816a0270716d9634b553bcc30962584ef1a 100644 (file)
@@ -29,6 +29,26 @@ &uart2 {
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
+&bsce {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
@@ -64,3 +84,11 @@ &ehci3 {
 &ohci3 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index a8dc01e3031317f577db8e5c5bfc8f08363b045a..02ce6b429dc47b104633491cee178499e677f1f4 100644 (file)
@@ -29,6 +29,22 @@ &uart2 {
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
index eee8b0e32681541266b70caa5d4b07ff789d35aa..d48462e091f176e6be77eeb301f769b40ef1afbc 100644 (file)
@@ -29,6 +29,22 @@ &uart2 {
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscc {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
index 739c2ef5663b5cec059ee167cbb92451bc010db7..3cfcaebe7f79db34e8c340ba71a1238f327b78c3 100644 (file)
@@ -29,6 +29,18 @@ &uart2 {
        status = "okay";
 };
 
+&bsca {
+       status = "okay";
+};
+
+&bscb {
+       status = "okay";
+};
+
+&bscd {
+       status = "okay";
+};
+
 &enet0 {
        status = "okay";
 };
@@ -40,3 +52,11 @@ &ehci0 {
 &ohci0 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index c678115f5b7f7c5b194d321b060b15df58cada4c..b18c46637d21b4ae7b85636d98a3353332022bbc 100644 (file)
@@ -1,5 +1,9 @@
 /dts-v1/;
 
+/memreserve/ 0x00000000 0x00001000;    /* YAMON exception vectors */
+/memreserve/ 0x00001000 0x000ef000;    /* YAMON */
+/memreserve/ 0x000f0000 0x00010000;    /* PIIX4 ISA memory */
+
 / {
        #address-cells = <1>;
        #size-cells = <1>;
index fb7734eadbf0e08faab7c6ab36b29851d3845e35..13d0439496a9d28d500b2d3e37b585e3f4541335 100644 (file)
@@ -107,7 +107,7 @@ wdt@18060008 {
                        miscintc: interrupt-controller@18060010 {
                                compatible = "qca,ar9132-misc-intc",
                                           "qca,ar7100-misc-intc";
-                               reg = <0x18060010 0x4>;
+                               reg = <0x18060010 0x8>;
 
                                interrupt-parent = <&cpuintc>;
                                interrupts = <6>;
diff --git a/arch/mips/boot/dts/xilfpga/Makefile b/arch/mips/boot/dts/xilfpga/Makefile
new file mode 100644 (file)
index 0000000..913a752
--- /dev/null
@@ -0,0 +1,9 @@
+dtb-$(CONFIG_XILFPGA_NEXYS4DDR)        += nexys4ddr.dtb
+
+obj-y                          += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj-                           += dummy.o
+
+always                         := $(dtb-y)
+clean-files    := *.dtb *.dtb.S
diff --git a/arch/mips/boot/dts/xilfpga/microAptiv.dtsi b/arch/mips/boot/dts/xilfpga/microAptiv.dtsi
new file mode 100644 (file)
index 0000000..81d518e
--- /dev/null
@@ -0,0 +1,21 @@
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "img,xilfpga";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,m14Kc";
+                       clocks  = <&ext>;
+                       reg = <0>;
+               };
+       };
+
+       ext: ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+       };
+};
diff --git a/arch/mips/boot/dts/xilfpga/nexys4ddr.dts b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts
new file mode 100644 (file)
index 0000000..686ebd1
--- /dev/null
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+#include "microAptiv.dtsi"
+
+/ {
+       compatible = "digilent,nexys4ddr";
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x08000000>;
+       };
+
+       cpuintc: interrupt-controller@0 {
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+               interrupt-controller;
+               compatible = "mti,cpu-interrupt-controller";
+       };
+
+       axi_gpio: gpio@10600000 {
+               #gpio-cells = <1>;
+               compatible = "xlnx,xps-gpio-1.00.a";
+               gpio-controller;
+               reg = <0x10600000 0x10000>;
+               xlnx,all-inputs = <0x0>;
+               xlnx,dout-default = <0x0>;
+               xlnx,gpio-width = <0x16>;
+               xlnx,interrupt-present = <0x0>;
+               xlnx,is-dual = <0x0>;
+               xlnx,tri-default = <0xffffffff>;
+       } ;
+
+       axi_uart16550: serial@10400000 {
+               compatible = "ns16550a";
+               reg = <0x10400000 0x10000>;
+
+               reg-shift = <2>;
+               reg-offset = <0x1000>;
+
+               clocks  = <&ext>;
+       };
+};
+
+&ext {
+       clock-frequency = <50000000>;
+};
index bd634259eab9d6b0f7d1b8e746d0b11c01f0950d..cd7101fb622705c26fa40bfd0f58ca4d23d05dcb 100644 (file)
@@ -1081,6 +1081,7 @@ void __init prom_free_prom_memory(void)
 
 int octeon_prune_device_tree(void);
 
+extern const char __appended_dtb;
 extern const char __dtb_octeon_3xxx_begin;
 extern const char __dtb_octeon_68xx_begin;
 void __init device_tree_init(void)
@@ -1088,11 +1089,19 @@ void __init device_tree_init(void)
        const void *fdt;
        bool do_prune;
 
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+       if (!fdt_check_header(&__appended_dtb)) {
+               fdt = &__appended_dtb;
+               do_prune = false;
+               pr_info("Using appended Device Tree.\n");
+       } else
+#endif
        if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
                fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
                if (fdt_check_header(fdt))
                        panic("Corrupt Device Tree passed to kernel.");
                do_prune = false;
+               pr_info("Using passed Device Tree.\n");
        } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
                fdt = &__dtb_octeon_68xx_begin;
                do_prune = true;
@@ -1106,8 +1115,6 @@ void __init device_tree_init(void)
        if (do_prune) {
                octeon_prune_device_tree();
                pr_info("Using internal Device Tree.\n");
-       } else {
-               pr_info("Using passed Device Tree.\n");
        }
        unflatten_and_copy_device_tree();
 }
index 1cdff6b6327d2753b41f76e348ee0bde97cc84dc..b3e7a1b61220bdff725a28661e39ab75e0744f72 100644 (file)
@@ -122,20 +122,20 @@ CONFIG_EEPROM_MAX6875=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDETAPE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SCH=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
+CONFIG_PATA_CMD64X=y
+CONFIG_PATA_IT8213=m
 CONFIG_PATA_SIL680=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
index f5585c8f35ad83539951a426b7b0871e4fcd8fb2..24dcb90b0f64b993dae12cd30a3e1aa5a6933f58 100644 (file)
@@ -8,7 +8,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
 CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
@@ -33,6 +33,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
 CONFIG_MTD_CFI=y
index 400a47ec1ef1e3a223da49d61c8abe0cdd2a04e3..4eb5d6e9cf8f1f256cbcf91b653746cb53ee0dde 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_MIPS_O32_FP64_SUPPORT=y
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
+CONFIG_RD_GZIP=y
 CONFIG_EXPERT=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
@@ -34,6 +34,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
 CONFIG_MTD_CFI=y
index 5135dc0b950aadbd325a0826c5918f8cca5bd6c4..2924ba34a01bf8d4bad7297a002ef2e4161d17ee 100644 (file)
@@ -31,9 +31,9 @@ CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_FW_LOADER=m
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_PHYLIB=m
 CONFIG_MARVELL_PHY=m
index 0126e66d60cbbf92a0a59a68abbf06ada87fe599..e94d266c4b97995f23b0b3e9c64fc7cd80adc2cf 100644 (file)
@@ -14,9 +14,9 @@ CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
index a75c65da08b4b7d573c45e0e429acd6dd54300c9..87435897fd50c802725be994843e07e1bc8ac105 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_MIPS32_N32=y
 CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_HIBERNATION=y
-CONFIG_PM_STD_PARTITION="/dev/hda3"
+CONFIG_PM_STD_PARTITION="/dev/sda3"
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -114,20 +114,16 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_TASK_IOCTL=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_VIA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_MACVLAN=m
 CONFIG_VETH=m
index 0179c7fa014f1c093099198bebe5585057eb93f2..e620a2c3eba478a955ab75303f57f7824d3bf61f 100644 (file)
@@ -35,11 +35,11 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_CMD64X=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_CMD64X=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
index 54cc3853d259de430f222e2a4f50d907201bd302..004cf52d1b7d81911e5e911a0dcee274be23b869 100644 (file)
@@ -108,16 +108,11 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_TASK_IOCTL=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_AMD74XX=y
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_AMD=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 61a4460d67d32b2c7d8d266f40c316c70aef5e7c..5afb4840aec75c3d41fb7a4fd08b8322d0437904 100644 (file)
@@ -241,14 +241,11 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
 CONFIG_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -265,6 +262,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_ATA=y
 CONFIG_ATA_PIIX=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index d41742dd26c8131279bc6a898461a043a78335ec..98f13879bb8fda832e3e73355f96af7defdcbc23 100644 (file)
@@ -248,17 +248,12 @@ CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index a7806e83ea0f1502cf0f78ceb5b0f29a86a07ee4..3b5d5913f548cddaf65f457da86ae245dee9f06d 100644 (file)
@@ -248,17 +248,12 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_VIRTIO_BLK=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
@@ -274,6 +269,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 4bce1f8ebe98294ad339bb6715bbf2e342088ffc..7f50dd67aa8d979e7e3515b2ff8537058c8ed0f0 100644 (file)
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index fb042ce86b4bc1da95d3b9297e6dfe88ed2f5dad..a9d433a17fcf60dd3e434d993958f633effd9df5 100644 (file)
@@ -81,15 +81,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index c83338a39917e17bd7cf1edd3f2b126f8339ab0a..2774ef06450596f7582db13c7749ce7a3b76f510 100644 (file)
@@ -85,15 +85,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index 62344648eb7a31a0e134db2d7eaf828dd8a012aa..9bbd2218f0bf518ff1c2aeceaec8695317556664 100644 (file)
@@ -80,15 +80,14 @@ CONFIG_NET_CLS_IND=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
-CONFIG_IDE=y
-# CONFIG_IDE_PROC_FS is not set
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_ADAPTEC is not set
index c388bff091482c9b871d80e86a27386e0fae1e9f..73221573275166e1ae7d044b1bad8dfa1b1f6d65 100644 (file)
@@ -244,17 +244,12 @@ CONFIG_CDROM_PKTCDVD=m
 CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
 CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
@@ -269,6 +264,13 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_OLDPIIX=y
+CONFIG_PATA_MPIIX=y
+CONFIG_ATA_GENERIC=y
+CONFIG_PATA_LEGACY=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
index 7a346605c498ae02e5a48245d03b1e028aacce96..a2c045fab6c58b38069db48b4d49dd9755a1789f 100644 (file)
@@ -27,9 +27,9 @@ CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_NETWORK_SECMARK=y
 CONFIG_CONNECTOR=m
 CONFIG_ATA_OVER_ETH=m
-# CONFIG_MISC_DEVICES is not set
-CONFIG_IDE=y
-CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_LEGACY=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
diff --git a/arch/mips/configs/xilfpga_defconfig b/arch/mips/configs/xilfpga_defconfig
new file mode 100644 (file)
index 0000000..ed1dce3
--- /dev/null
@@ -0,0 +1,40 @@
+CONFIG_MACH_XILFPGA=y
+# CONFIG_COMPACTION is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,115200"
index 37f84078e78abbe3f6b85841461c8bccc62d6c9a..940760844e2fe98a8e3958e975b1cbd674786675 100644 (file)
 
 #include <asm/signal.h>
 #include <asm/siginfo.h>
+#include <asm/vdso.h>
 
 struct mips_abi {
        int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
                                  struct pt_regs *regs, sigset_t *set);
-       const unsigned long     signal_return_offset;
        int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
                                     struct pt_regs *regs, sigset_t *set);
-       const unsigned long     rt_signal_return_offset;
        const unsigned long     restart;
 
        unsigned        off_sc_fpregs;
        unsigned        off_sc_fpc_csr;
        unsigned        off_sc_used_math;
+
+       struct mips_vdso_image *vdso;
 };
 
 #endif /* _ASM_ABI_H */
index f82d3af07931656a1f295b07972d6717df89a30d..835b402e4574fa1a27da780da9ae398bbf3bb276 100644 (file)
@@ -507,7 +507,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
  * @u: ...unless v is equal to u.
  *
  * Atomically adds @a to @v, so long as it was not @u.
- * Returns the old value of @v.
+ * Returns true iff @v was not @u.
  */
 static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 {
index 8c34484cea827f516591dd9f3c775d36e81fac7b..a00857b135c348eb104e8dae4dfdda4ccbe8563d 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _ASM_BCACHE_H
 #define _ASM_BCACHE_H
 
+#include <linux/types.h>
 
 /* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
    chipset implemented caches. On machines with other CPUs the CPU does the
@@ -18,6 +19,9 @@ struct bcache_ops {
        void (*bc_disable)(void);
        void (*bc_wback_inv)(unsigned long page, unsigned long size);
        void (*bc_inv)(unsigned long page, unsigned long size);
+       void (*bc_prefetch_enable)(void);
+       void (*bc_prefetch_disable)(void);
+       bool (*bc_prefetch_is_enabled)(void);
 };
 
 extern void indy_sc_init(void);
@@ -46,6 +50,26 @@ static inline void bc_inv(unsigned long page, unsigned long size)
        bcops->bc_inv(page, size);
 }
 
+static inline void bc_prefetch_enable(void)
+{
+       if (bcops->bc_prefetch_enable)
+               bcops->bc_prefetch_enable();
+}
+
+static inline void bc_prefetch_disable(void)
+{
+       if (bcops->bc_prefetch_disable)
+               bcops->bc_prefetch_disable();
+}
+
+static inline bool bc_prefetch_is_enabled(void)
+{
+       if (bcops->bc_prefetch_is_enabled)
+               return bcops->bc_prefetch_is_enabled();
+
+       return false;
+}
+
 #else /* !defined(CONFIG_BOARD_SCACHE) */
 
 /* Not R4000 / R4400 / R4600 / R5000.  */
@@ -54,6 +78,9 @@ static inline void bc_inv(unsigned long page, unsigned long size)
 #define bc_disable() do { } while (0)
 #define bc_wback_inv(page, size) do { } while (0)
 #define bc_inv(page, size) do { } while (0)
+#define bc_prefetch_enable() do { } while (0)
+#define bc_prefetch_disable() do { } while (0)
+#define bc_prefetch_is_enabled() 0
 
 #endif /* !defined(CONFIG_BOARD_SCACHE) */
 
index bece2064cc8cbf24f6c36c603b501c6b0dc19edd..c06dbf8ba937093d81b33cd14e00d9c74c944de6 100644 (file)
@@ -84,6 +84,17 @@ void mips_cdmm_driver_unregister(struct mips_cdmm_driver *);
        module_driver(__mips_cdmm_driver, mips_cdmm_driver_register, \
                        mips_cdmm_driver_unregister)
 
+/*
+ * builtin_mips_cdmm_driver() - Helper macro for drivers that don't do anything
+ * special in init and have no exit. This eliminates some boilerplate. Each
+ * driver may only use this macro once, and calling it replaces device_initcall
+ * (or in some cases, the legacy __initcall). This is meant to be a direct
+ * parallel of module_mips_cdmm_driver() above but without the __exit stuff that
+ * is not used for builtin cases.
+ */
+#define builtin_mips_cdmm_driver(__mips_cdmm_driver) \
+       builtin_driver(__mips_cdmm_driver, mips_cdmm_driver_register)
+
 /* drivers/tty/mips_ejtag_fdc.c */
 
 #ifdef CONFIG_MIPS_EJTAG_FDC_EARLYCON
diff --git a/arch/mips/include/asm/clocksource.h b/arch/mips/include/asm/clocksource.h
new file mode 100644 (file)
index 0000000..3deb1d0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_CLOCKSOURCE_H
+#define __ASM_CLOCKSOURCE_H
+
+#include <linux/types.h>
+
+/* VDSO clocksources. */
+#define VDSO_CLOCK_NONE                0       /* No suitable clocksource. */
+#define VDSO_CLOCK_R4K         1       /* Use the coprocessor 0 count. */
+#define VDSO_CLOCK_GIC         2       /* Use the GIC. */
+
+/**
+ * struct arch_clocksource_data - Architecture-specific clocksource information.
+ * @vdso_clock_mode: Method the VDSO should use to access the clocksource.
+ */
+struct arch_clocksource_data {
+       u8 vdso_clock_mode;
+};
+
+#endif /* __ASM_CLOCKSOURCE_H */
index c4bd54a7f5ce1675de61705a5b8779846e012589..a9580097cba8fe0d7db36793c8f8cf831323579e 100644 (file)
@@ -130,6 +130,8 @@ typedef union compat_sigval {
        compat_uptr_t   sival_ptr;
 } compat_sigval_t;
 
+/* Can't use the generic version because si_code and si_errno are swapped */
+
 #define SI_PAD_SIZE32  (128/sizeof(int) - 3)
 
 typedef struct compat_siginfo {
@@ -138,57 +140,61 @@ typedef struct compat_siginfo {
        int si_errno;
 
        union {
-               int _pad[SI_PAD_SIZE32];
+               int _pad[128 / sizeof(int) - 3];
 
                /* kill() */
                struct {
                        compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid_t _uid;    /* sender's uid */
+                       __compat_uid32_t _uid;  /* sender's uid */
                } _kill;
 
+               /* POSIX.1b timers */
+               struct {
+                       compat_timer_t _tid;    /* timer id */
+                       int _overrun;           /* overrun count */
+                       compat_sigval_t _sigval;        /* same as below */
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       compat_pid_t _pid;      /* sender's pid */
+                       __compat_uid32_t _uid;  /* sender's uid */
+                       compat_sigval_t _sigval;
+               } _rt;
+
                /* SIGCHLD */
                struct {
                        compat_pid_t _pid;      /* which child */
-                       __compat_uid_t _uid;    /* sender's uid */
+                       __compat_uid32_t _uid;  /* sender's uid */
                        int _status;            /* exit code */
                        compat_clock_t _utime;
                        compat_clock_t _stime;
                } _sigchld;
 
-               /* IRIX SIGCHLD */
-               struct {
-                       compat_pid_t _pid;      /* which child */
-                       compat_clock_t _utime;
-                       int _status;            /* exit code */
-                       compat_clock_t _stime;
-               } _irix_sigchld;
-
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
                struct {
-                       s32 _addr; /* faulting insn/memory ref. */
+                       compat_uptr_t _addr;    /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+                       int _trapno;    /* TRAP # which caused the signal */
+#endif
+                       short _addr_lsb; /* LSB of the reported address */
+                       struct {
+                               compat_uptr_t _lower;
+                               compat_uptr_t _upper;
+                       } _addr_bnd;
                } _sigfault;
 
-               /* SIGPOLL, SIGXFSZ (To do ...)  */
+               /* SIGPOLL */
                struct {
-                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
                        int _fd;
                } _sigpoll;
 
-               /* POSIX.1b timers */
-               struct {
-                       timer_t _tid;           /* timer id */
-                       int _overrun;           /* overrun count */
-                       compat_sigval_t _sigval;/* same as below */
-                       int _sys_private;       /* not to be passed to user */
-               } _timer;
-
-               /* POSIX.1b signals */
                struct {
-                       compat_pid_t _pid;      /* sender's pid */
-                       __compat_uid_t _uid;    /* sender's uid */
-                       compat_sigval_t _sigval;
-               } _rt;
-
+                       compat_uptr_t _call_addr; /* calling insn */
+                       int _syscall;   /* triggering system call number */
+                       compat_uint_t _arch;    /* AUDIT_ARCH_* of syscall */
+               } _sigsys;
        } _sifields;
 } compat_siginfo_t;
 
index fe67f12ac2393b23705b4a094bbf8c3b7cc77166..d1e04c943f5f7c7d9ec232851e14d9b5c4215496 100644 (file)
 #endif
 
 #ifndef cpu_has_rixi
-# ifdef CONFIG_64BIT
-# define cpu_has_rixi          (cpu_data[0].options & MIPS_CPU_RIXI)
-# else /* CONFIG_32BIT */
-# define cpu_has_rixi          ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits)
-# endif
+#define cpu_has_rixi           (cpu_data[0].options & MIPS_CPU_RIXI)
 #endif
 
 #ifndef cpu_has_mmips
diff --git a/arch/mips/include/asm/debug.h b/arch/mips/include/asm/debug.h
new file mode 100644 (file)
index 0000000..254f00d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_DEBUG_H__
+#define __MIPS_ASM_DEBUG_H__
+
+#include <linux/dcache.h>
+
+/*
+ * mips_debugfs_dir corresponds to the "mips" directory at the top level
+ * of the DebugFS hierarchy. MIPS-specific DebugFS entires should be
+ * placed beneath this directory.
+ */
+extern struct dentry *mips_debugfs_dir;
+
+#endif /* __MIPS_ASM_DEBUG_H__ */
index 53b26933b12cea365457f95172fbde6990043ff1..b01a6ff468e00aab5d185a9dd53023101b34f2b7 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _ASM_ELF_H
 #define _ASM_ELF_H
 
+#include <linux/auxvec.h>
 #include <linux/fs.h>
 #include <uapi/linux/elf.h>
 
@@ -419,6 +420,12 @@ extern const char *__elf_platform;
 #define ELF_ET_DYN_BASE                (TASK_SIZE / 3 * 2)
 #endif
 
+#define ARCH_DLINFO                                                    \
+do {                                                                   \
+       NEW_AUX_ENT(AT_SYSINFO_EHDR,                                    \
+                   (unsigned long)current->mm->context.vdso);          \
+} while (0)
+
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
 extern int arch_setup_additional_pages(struct linux_binprm *bprm,
index f3e6978aad704c4a15bad1971c55625f2e378f6e..d0ef8b4892bbe6af327a0b351df93f948c413b37 100644 (file)
 
 #include <asm/bootinfo.h>      /* For cleaner code... */
 
-enum fw_memtypes {
-       fw_dontuse,
-       fw_code,
-       fw_free,
-};
-
-typedef struct {
-       unsigned long base;     /* Within KSEG0 */
-       unsigned int size;      /* bytes */
-       enum fw_memtypes type;  /* fw_memtypes */
-} fw_memblock_t;
-
-/* Maximum number of memory block descriptors. */
-#define FW_MAX_MEMBLOCKS       32
-
 extern int fw_argc;
 extern int *_fw_argv;
 extern int *_fw_envp;
@@ -38,7 +23,6 @@ extern int *_fw_envp;
 
 extern void fw_init_cmdline(void);
 extern char *fw_getcmdline(void);
-extern fw_memblock_t *fw_getmdesc(int);
 extern void fw_meminit(void);
 extern char *fw_getenv(char *name);
 extern unsigned long fw_getenvl(char *name);
index 1461c10c1c4c4e9a9c5c3e0ec1384b433e4f312c..71e4096a2145667328f9535d6c3ea93617881154 100644 (file)
@@ -48,11 +48,6 @@ extern enum bcm47xx_bus_type bcm47xx_bus_type;
 void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
                        bool fallback);
 
-#ifdef CONFIG_BCM47XX_SSB
-void bcm47xx_fill_ssb_boardinfo(struct ssb_boardinfo *boardinfo,
-                               const char *prefix);
-#endif
-
 void bcm47xx_set_system_type(u16 chip_id);
 
 #endif /* __ASM_BCM47XX_H */
index 133336b493b67c4822e79a2965e93300adbab853..dd6005b75e0c0bb594e657ede11df74b21776852 100644 (file)
 #define SOC_ID_VRX268_2                0x00C /* v1.2 */
 #define SOC_ID_GRX288_2                0x00D /* v1.2 */
 #define SOC_ID_GRX282_2                0x00E /* v1.2 */
+#define SOC_ID_VRX220          0x000
+
+#define SOC_ID_ARX362          0x004
+#define SOC_ID_ARX368          0x005
+#define SOC_ID_ARX382          0x007
+#define SOC_ID_ARX388          0x008
+#define SOC_ID_URX388          0x009
+#define SOC_ID_GRX383          0x010
+#define SOC_ID_GRX369          0x011
+#define SOC_ID_GRX387          0x00F
+#define SOC_ID_GRX389          0x012
 
  /* SoC Types */
 #define SOC_TYPE_DANUBE                0x01
@@ -43,6 +54,9 @@
 #define SOC_TYPE_VR9           0x04 /* v1.1 */
 #define SOC_TYPE_VR9_2         0x05 /* v1.2 */
 #define SOC_TYPE_AMAZON_SE     0x06
+#define SOC_TYPE_AR10          0x07
+#define SOC_TYPE_GRX390                0x08
+#define SOC_TYPE_VRX220                0x09
 
 /* BOOT_SEL - find what boot media we have */
 #define BS_EXT_ROM             0x0
diff --git a/arch/mips/include/asm/mach-malta/malta-dtshim.h b/arch/mips/include/asm/mach-malta/malta-dtshim.h
new file mode 100644 (file)
index 0000000..cfd7776
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_MALTA_DTSHIM_H__
+#define __MIPS_MALTA_DTSHIM_H__
+
+#include <linux/init.h>
+
+#ifdef CONFIG_MIPS_MALTA
+
+extern void __init *malta_dt_shim(void *fdt);
+
+#else /* !CONFIG_MIPS_MALTA */
+
+static inline void *malta_dt_shim(void *fdt)
+{
+       return fdt;
+}
+
+#endif /* !CONFIG_MIPS_MALTA */
+
+#endif /* __MIPS_MALTA_DTSHIM_H__ */
index 1976fb815fd10c5275b0e04a1c008812fc847e6c..455d406e8ddf1667e4c2212aacfe985c2eb08be8 100644 (file)
 #ifndef _MT7620_REGS_H_
 #define _MT7620_REGS_H_
 
-enum mt762x_soc_type {
-       MT762X_SOC_UNKNOWN = 0,
-       MT762X_SOC_MT7620A,
-       MT762X_SOC_MT7620N,
-       MT762X_SOC_MT7628AN,
-};
-
 #define MT7620_SYSC_BASE               0x10000000
 
 #define SYSC_REG_CHIP_NAME0            0x00
 #define SYSC_REG_CHIP_NAME1            0x04
+#define SYSC_REG_EFUSE_CFG             0x08
 #define SYSC_REG_CHIP_REV              0x0c
 #define SYSC_REG_SYSTEM_CONFIG0                0x10
 #define SYSC_REG_SYSTEM_CONFIG1                0x14
index bd93014490df39eebce2df057d5b3e84f2130aeb..4c9fba68c8b2490bfaf98b2f1ec8b2fc77f0ed5f 100644 (file)
 #ifndef _RALINK_REGS_H_
 #define _RALINK_REGS_H_
 
+enum ralink_soc_type {
+       RALINK_UNKNOWN = 0,
+       RT2880_SOC,
+       RT3883_SOC,
+       RT305X_SOC_RT3050,
+       RT305X_SOC_RT3052,
+       RT305X_SOC_RT3350,
+       RT305X_SOC_RT3352,
+       RT305X_SOC_RT5350,
+       MT762X_SOC_MT7620A,
+       MT762X_SOC_MT7620N,
+       MT762X_SOC_MT7621AT,
+       MT762X_SOC_MT7628AN,
+       MT762X_SOC_MT7688,
+};
+extern enum ralink_soc_type ralink_soc;
+
 extern __iomem void *rt_sysc_membase;
 extern __iomem void *rt_memc_membase;
 
index 96f731bac79a4a9941f0fb5cc5198621f4ee7f9f..2eea79331a14bf040b164ce294e2ce3a0bb99ba7 100644 (file)
 #ifndef _RT305X_REGS_H_
 #define _RT305X_REGS_H_
 
-enum rt305x_soc_type {
-       RT305X_SOC_UNKNOWN = 0,
-       RT305X_SOC_RT3050,
-       RT305X_SOC_RT3052,
-       RT305X_SOC_RT3350,
-       RT305X_SOC_RT3352,
-       RT305X_SOC_RT5350,
-};
-
-extern enum rt305x_soc_type rt305x_soc;
+extern enum ralink_soc_type ralink_soc;
 
 static inline int soc_is_rt3050(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3050;
+       return ralink_soc == RT305X_SOC_RT3050;
 }
 
 static inline int soc_is_rt3052(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3052;
+       return ralink_soc == RT305X_SOC_RT3052;
 }
 
 static inline int soc_is_rt305x(void)
@@ -41,17 +32,17 @@ static inline int soc_is_rt305x(void)
 
 static inline int soc_is_rt3350(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3350;
+       return ralink_soc == RT305X_SOC_RT3350;
 }
 
 static inline int soc_is_rt3352(void)
 {
-       return rt305x_soc == RT305X_SOC_RT3352;
+       return ralink_soc == RT305X_SOC_RT3352;
 }
 
 static inline int soc_is_rt5350(void)
 {
-       return rt305x_soc == RT305X_SOC_RT5350;
+       return ralink_soc == RT305X_SOC_RT5350;
 }
 
 #define RT305X_SYSC_BASE               0x10000000
diff --git a/arch/mips/include/asm/mach-xilfpga/irq.h b/arch/mips/include/asm/mach-xilfpga/irq.h
new file mode 100644 (file)
index 0000000..0132a5b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+#define __MIPS_ASM_MACH_XILFPGA_IRQ_H__
+
+#define NR_IRQS 32
+
+#include_next <irq.h>
+
+#endif /* __MIPS_ASM_MACH_XILFPGA_IRQ_H__ */
index 1f1927ab42690b284257faa8991f4cff31a3264d..6516e9da51334916b04b6f8689a0857faad5f0ca 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef __MIPS_ASM_MIPS_CM_H__
 #define __MIPS_ASM_MIPS_CM_H__
 
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/io.h>
 #include <linux/types.h>
@@ -36,12 +37,12 @@ extern phys_addr_t __mips_cm_phys_base(void);
 /*
  * mips_cm_is64 - determine CM register width
  *
- * The CM register width is processor and CM specific. A 64-bit processor
- * usually has a 64-bit CM and a 32-bit one has a 32-bit CM but a 64-bit
- * processor could come with a 32-bit CM. Moreover, accesses on 64-bit CMs
- * can be done either using regular 64-bit load/store instructions, or 32-bit
- * load/store instruction on 32-bit register pairs. We opt for using 64-bit
- * accesses on 64-bit CMs and kernels and 32-bit in any other case.
+ * The CM register width is determined by the version of the CM, with CM3
+ * introducing 64 bit GCRs and all prior CM versions having 32 bit GCRs.
+ * However we may run a kernel built for MIPS32 on a system with 64 bit GCRs,
+ * or vice-versa. This variable indicates the width of the memory accesses
+ * that the kernel will perform to GCRs, which may differ from the actual
+ * width of the GCRs.
  *
  * It's set to 0 for 32-bit accesses and 1 for 64-bit accesses.
  */
@@ -125,7 +126,17 @@ static inline u32 read32_gcr_##name(void)                  \
                                                                \
 static inline u64 read64_gcr_##name(void)                      \
 {                                                              \
-       return __raw_readq(addr_gcr_##name());                  \
+       void __iomem *addr = addr_gcr_##name();                 \
+       u64 ret;                                                \
+                                                               \
+       if (mips_cm_is64) {                                     \
+               ret = __raw_readq(addr);                        \
+       } else {                                                \
+               ret = __raw_readl(addr);                        \
+               ret |= (u64)__raw_readl(addr + 0x4) << 32;      \
+       }                                                       \
+                                                               \
+       return ret;                                             \
 }                                                              \
                                                                \
 static inline unsigned long read_gcr_##name(void)              \
@@ -195,6 +206,8 @@ BUILD_CM_R_(gic_status,             MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,                MIPS_CM_GCB_OFS + 0xf0)
 BUILD_CM_RW(l2_config,         MIPS_CM_GCB_OFS + 0x130)
 BUILD_CM_RW(sys_config2,       MIPS_CM_GCB_OFS + 0x150)
+BUILD_CM_RW(l2_pft_control,    MIPS_CM_GCB_OFS + 0x300)
+BUILD_CM_RW(l2_pft_control_b,  MIPS_CM_GCB_OFS + 0x308)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -245,11 +258,14 @@ BUILD_CM_Cx_R_(tcid_8_priority,   0x80)
                 ((minor) << CM_GCR_REV_MINOR_SHF))
 
 #define CM_REV_CM2                             CM_ENCODE_REV(6, 0)
+#define CM_REV_CM2_5                           CM_ENCODE_REV(7, 0)
 #define CM_REV_CM3                             CM_ENCODE_REV(8, 0)
 
 /* GCR_ERROR_CAUSE register fields */
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_SHF         27
 #define CM_GCR_ERROR_CAUSE_ERRTYPE_MSK         (_ULCAST_(0x1f) << 27)
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF                58
+#define CM3_GCR_ERROR_CAUSE_ERRTYPE_MSK                GENMASK_ULL(63, 58)
 #define CM_GCR_ERROR_CAUSE_ERRINFO_SHF         0
 #define CM_GCR_ERROR_CAUSE_ERRINGO_MSK         (_ULCAST_(0x7ffffff) << 0)
 
@@ -321,6 +337,20 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_SYS_CONFIG2_MAXVPW_SHF          0
 #define CM_GCR_SYS_CONFIG2_MAXVPW_MSK          (_ULCAST_(0xf) << 0)
 
+/* GCR_L2_PFT_CONTROL register fields */
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_SHF     12
+#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK     (_ULCAST_(0xfffff) << 12)
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_SHF                8
+#define CM_GCR_L2_PFT_CONTROL_PFTEN_MSK                (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_NPFT_SHF         0
+#define CM_GCR_L2_PFT_CONTROL_NPFT_MSK         (_ULCAST_(0xff) << 0)
+
+/* GCR_L2_PFT_CONTROL_B register fields */
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_SHF                8
+#define CM_GCR_L2_PFT_CONTROL_B_CEN_MSK                (_ULCAST_(0x1) << 8)
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_SHF     0
+#define CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK     (_ULCAST_(0xff) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF    0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK    (_ULCAST_(0xff) << 0)
@@ -329,11 +359,15 @@ BUILD_CM_Cx_R_(tcid_8_priority,   0x80)
 #define CM_GCR_Cx_CONFIG_IOCUTYPE_SHF          10
 #define CM_GCR_Cx_CONFIG_IOCUTYPE_MSK          (_ULCAST_(0x3) << 10)
 #define CM_GCR_Cx_CONFIG_PVPE_SHF              0
-#define CM_GCR_Cx_CONFIG_PVPE_MSK              (_ULCAST_(0x1ff) << 0)
+#define CM_GCR_Cx_CONFIG_PVPE_MSK              (_ULCAST_(0x3ff) << 0)
 
 /* GCR_Cx_OTHER register fields */
 #define CM_GCR_Cx_OTHER_CORENUM_SHF            16
 #define CM_GCR_Cx_OTHER_CORENUM_MSK            (_ULCAST_(0xffff) << 16)
+#define CM3_GCR_Cx_OTHER_CORE_SHF              8
+#define CM3_GCR_Cx_OTHER_CORE_MSK              (_ULCAST_(0x3f) << 8)
+#define CM3_GCR_Cx_OTHER_VP_SHF                        0
+#define CM3_GCR_Cx_OTHER_VP_MSK                        (_ULCAST_(0x7) << 0)
 
 /* GCR_Cx_RESET_BASE register fields */
 #define CM_GCR_Cx_RESET_BASE_BEVEXCBASE_SHF    12
@@ -444,4 +478,32 @@ static inline unsigned int mips_cm_vp_id(unsigned int cpu)
        return (core * mips_cm_max_vp_width()) + vp;
 }
 
+#ifdef CONFIG_MIPS_CM
+
+/**
+ * mips_cm_lock_other - lock access to another core
+ * @core: the other core to be accessed
+ * @vp: the VP within the other core to be accessed
+ *
+ * Call before operating upon a core via the 'other' register region in
+ * order to prevent the region being moved during access. Must be followed
+ * by a call to mips_cm_unlock_other.
+ */
+extern void mips_cm_lock_other(unsigned int core, unsigned int vp);
+
+/**
+ * mips_cm_unlock_other - unlock access to another core
+ *
+ * Call after operating upon another core via the 'other' register region.
+ * Must be called after mips_cm_lock_other.
+ */
+extern void mips_cm_unlock_other(void);
+
+#else /* !CONFIG_MIPS_CM */
+
+static inline void mips_cm_lock_other(unsigned int core) { }
+static inline void mips_cm_unlock_other(void) { }
+
+#endif /* !CONFIG_MIPS_CM */
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
index f386f32702f17f75782ba9a58ffe5fa0ee37e186..e09035239e5383117947fcabe8920cdf8d7608f1 100644 (file)
@@ -149,7 +149,8 @@ BUILD_CPC_Cx_RW(other,              0x10)
  * core: the other core to be accessed
  *
  * Call before operating upon a core via the 'other' register region in
- * order to prevent the region being moved during access. Must be followed
+ * order to prevent the region being moved during access. Must be called
+ * within the bounds of a mips_cm_{lock,unlock}_other pair, and followed
  * by a call to mips_cpc_unlock_other.
  */
 extern void mips_cpc_lock_other(unsigned int core);
index c64781cf649f86b4ca4eec0fee38ba4c4da523e7..e43aca183c9918d4138f000c4a385659f8523eae 100644 (file)
@@ -50,7 +50,9 @@
 #define CP0_PAGEMASK $5
 #define CP0_WIRED $6
 #define CP0_INFO $7
+#define CP0_HWRENA $7, 0
 #define CP0_BADVADDR $8
+#define CP0_BADINSTR $8, 1
 #define CP0_COUNT $9
 #define CP0_ENTRYHI $10
 #define CP0_COMPARE $11
 #define CP0_CAUSE $13
 #define CP0_EPC $14
 #define CP0_PRID $15
+#define CP0_EBASE $15, 1
+#define CP0_CMGCRBASE $15, 3
 #define CP0_CONFIG $16
+#define CP0_CONFIG3 $16, 3
+#define CP0_CONFIG5 $16, 5
 #define CP0_LLADDR $17
 #define CP0_WATCHLO $18
 #define CP0_WATCHHI $19
 #define R3K_ENTRYLO_N          (_ULCAST_(1) << 11)
 
 /* MIPS32/64 EntryLo bit definitions */
-#ifdef CONFIG_64BIT
-/* as read by dmfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 62)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 63)
-#else
-/* as read by mfc0 */
-#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << 30)
-#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << 31)
-#endif
+#define MIPS_ENTRYLO_PFN_SHIFT 6
+#define MIPS_ENTRYLO_XI                (_ULCAST_(1) << (BITS_PER_LONG - 2))
+#define MIPS_ENTRYLO_RI                (_ULCAST_(1) << (BITS_PER_LONG - 1))
 
 /*
  * Values for PageMask register
index 89dd7fed1a570cf312e74b9216342fa6abbfdf22..2046c023022406d8a336197db13df1a75b1e8021 100644 (file)
@@ -33,7 +33,7 @@
 #define PAGE_SHIFT     16
 #endif
 #define PAGE_SIZE      (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK      (~((1 << PAGE_SHIFT) - 1))
+#define PAGE_MASK      (~(PAGE_SIZE - 1))
 
 /*
  * This is used for calculating the real page sizes
@@ -200,8 +200,9 @@ static inline int pfn_valid(unsigned long pfn)
 {
        /* avoid <linux/mm.h> include hell */
        extern unsigned long max_mapnr;
+       unsigned long pfn_offset = ARCH_PFN_OFFSET;
 
-       return pfn >= ARCH_PFN_OFFSET && pfn < max_mapnr;
+       return pfn >= pfn_offset && pfn < max_mapnr;
 }
 
 #elif defined(CONFIG_SPARSEMEM)
index 59ee6dcf6eed9fd2b336347b0d674070baf9f298..3f832c3dd8f5f1cad76461b47ee00a0b7f85722d 100644 (file)
@@ -36,12 +36,6 @@ extern unsigned int vced_count, vcei_count;
  */
 #define HAVE_ARCH_PICK_MMAP_LAYOUT 1
 
-/*
- * A special page (the vdso) is mapped into all processes at the very
- * top of the virtual memory space.
- */
-#define SPECIAL_PAGES_SIZE PAGE_SIZE
-
 #ifdef CONFIG_32BIT
 #ifdef CONFIG_KVM_GUEST
 /* User space process size is limited to 1GB in KVM Guest Mode */
@@ -80,7 +74,7 @@ extern unsigned int vced_count, vcei_count;
 
 #endif
 
-#define STACK_TOP      ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
+#define STACK_TOP      (TASK_SIZE & PAGE_MASK)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
index cca56aa40ff4a1cd475457c16783bc71855f43c5..8f4ca5dd992b1e8ed28791488c1ebe8403f80d7c 100644 (file)
 /*
- * 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) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
  *
- * Copyright (C) 2009 Cavium Networks
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
  */
 
 #ifndef __ASM_VDSO_H
 #define __ASM_VDSO_H
 
-#include <linux/types.h>
+#include <linux/mm_types.h>
 
+#include <asm/barrier.h>
 
-#ifdef CONFIG_32BIT
-struct mips_vdso {
-       u32 signal_trampoline[2];
-       u32 rt_signal_trampoline[2];
+/**
+ * struct mips_vdso_image - Details of a VDSO image.
+ * @data: Pointer to VDSO image data (page-aligned).
+ * @size: Size of the VDSO image data (page-aligned).
+ * @off_sigreturn: Offset of the sigreturn() trampoline.
+ * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
+ * @mapping: Special mapping structure.
+ *
+ * This structure contains details of a VDSO image, including the image data
+ * and offsets of certain symbols required by the kernel. It is generated as
+ * part of the VDSO build process, aside from the mapping page array, which is
+ * populated at runtime.
+ */
+struct mips_vdso_image {
+       void *data;
+       unsigned long size;
+
+       unsigned long off_sigreturn;
+       unsigned long off_rt_sigreturn;
+
+       struct vm_special_mapping mapping;
 };
-#else  /* !CONFIG_32BIT */
-struct mips_vdso {
-       u32 o32_signal_trampoline[2];
-       u32 o32_rt_signal_trampoline[2];
-       u32 rt_signal_trampoline[2];
-       u32 n32_rt_signal_trampoline[2];
+
+/*
+ * The following structures are auto-generated as part of the build for each
+ * ABI by genvdso, see arch/mips/vdso/Makefile.
+ */
+
+extern struct mips_vdso_image vdso_image;
+
+#ifdef CONFIG_MIPS32_O32
+extern struct mips_vdso_image vdso_image_o32;
+#endif
+
+#ifdef CONFIG_MIPS32_N32
+extern struct mips_vdso_image vdso_image_n32;
+#endif
+
+/**
+ * union mips_vdso_data - Data provided by the kernel for the VDSO.
+ * @xtime_sec:         Current real time (seconds part).
+ * @xtime_nsec:                Current real time (nanoseconds part, shifted).
+ * @wall_to_mono_sec:  Wall-to-monotonic offset (seconds part).
+ * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part).
+ * @seq_count:         Counter to synchronise updates (odd = updating).
+ * @cs_shift:          Clocksource shift value.
+ * @clock_mode:                Clocksource to use for time functions.
+ * @cs_mult:           Clocksource multiplier value.
+ * @cs_cycle_last:     Clock cycle value at last update.
+ * @cs_mask:           Clocksource mask value.
+ * @tz_minuteswest:    Minutes west of Greenwich (from timezone).
+ * @tz_dsttime:                Type of DST correction (from timezone).
+ *
+ * This structure contains data needed by functions within the VDSO. It is
+ * populated by the kernel and mapped read-only into user memory. The time
+ * fields are mirrors of internal data from the timekeeping infrastructure.
+ *
+ * Note: Care should be taken when modifying as the layout must remain the same
+ * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
+ */
+union mips_vdso_data {
+       struct {
+               u64 xtime_sec;
+               u64 xtime_nsec;
+               u32 wall_to_mono_sec;
+               u32 wall_to_mono_nsec;
+               u32 seq_count;
+               u32 cs_shift;
+               u8 clock_mode;
+               u32 cs_mult;
+               u64 cs_cycle_last;
+               u64 cs_mask;
+               s32 tz_minuteswest;
+               s32 tz_dsttime;
+       };
+
+       u8 page[PAGE_SIZE];
 };
-#endif /* CONFIG_32BIT */
+
+static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
+{
+       u32 seq;
+
+       while (true) {
+               seq = ACCESS_ONCE(data->seq_count);
+               if (likely(!(seq & 1))) {
+                       /* Paired with smp_wmb() in vdso_data_write_*(). */
+                       smp_rmb();
+                       return seq;
+               }
+
+               cpu_relax();
+       }
+}
+
+static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
+                                       u32 start_seq)
+{
+       /* Paired with smp_wmb() in vdso_data_write_*(). */
+       smp_rmb();
+       return unlikely(data->seq_count != start_seq);
+}
+
+static inline void vdso_data_write_begin(union mips_vdso_data *data)
+{
+       ++data->seq_count;
+
+       /* Ensure sequence update is written before other data page values. */
+       smp_wmb();
+}
+
+static inline void vdso_data_write_end(union mips_vdso_data *data)
+{
+       /* Ensure data values are written before updating sequence again. */
+       smp_wmb();
+       ++data->seq_count;
+}
 
 #endif /* __ASM_VDSO_H */
index 96fe7395ed8dc8df6d2675bf31626b45133c15e4..f2cf4146114679253195769bab10b859f41026d6 100644 (file)
@@ -1,9 +1,9 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += auxvec.h
 generic-y += ipcbuf.h
 
+header-y += auxvec.h
 header-y += bitfield.h
 header-y += bitsperlong.h
 header-y += break.h
diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..c9c7195
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* Location of VDSO image. */
+#define AT_SYSINFO_EHDR                33
+
+#endif /* __ASM_AUXVEC_H */
index 459cb017306c21eb63259b8cb0a406c65080cc8b..934b15b5b575f15b04fae0bf44065440773f7593 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/power_supply.h>
 #include <linux/power/jz4740-battery.h>
 #include <linux/power/gpio-charger.h>
+#include <linux/pwm.h>
 
 #include <asm/mach-jz4740/gpio.h>
 #include <asm/mach-jz4740/jz4740_fb.h>
@@ -34,8 +35,6 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
-#include <linux/leds_pwm.h>
-
 #include <asm/mach-jz4740/platform.h>
 
 #include "clock.h"
@@ -399,13 +398,15 @@ static struct platform_device avt2_usb_regulator_device = {
        }
 };
 
+static struct pwm_lookup qi_lb60_pwm_lookup[] = {
+       PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
+                  PWM_POLARITY_NORMAL),
+};
+
 /* beeper */
 static struct platform_device qi_lb60_pwm_beeper = {
        .name = "pwm-beeper",
        .id = -1,
-       .dev = {
-               .platform_data = (void *)4,
-       },
 };
 
 /* charger */
@@ -491,6 +492,8 @@ static int __init qi_lb60_init_platform_devices(void)
                platform_device_register(&jz4740_usb_ohci_device);
        }
 
+       pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
+
        return platform_add_devices(jz_platform_devices,
                                        ARRAY_SIZE(jz_platform_devices));
 
index d982be1ea1c3f3125da9762f3e1b203ae939b1d0..68e2b7db9348f1d168666411544a90bd080d0ae0 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_MIPS_MT_FPAFF)   += mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMP)      += smp-mt.o
 obj-$(CONFIG_MIPS_CMP)         += smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)         += smp-cps.o cps-vec.o
+obj-$(CONFIG_MIPS_CPS_NS16550) += cps-vec-ns16550.o
 obj-$(CONFIG_MIPS_GIC_IPI)     += smp-gic.o
 obj-$(CONFIG_MIPS_SPRAM)       += spram.o
 
diff --git a/arch/mips/kernel/cps-vec-ns16550.S b/arch/mips/kernel/cps-vec-ns16550.S
new file mode 100644 (file)
index 0000000..6d246ad
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <linux/serial_reg.h>
+
+#define UART_TX_OFS    (UART_TX << CONFIG_MIPS_CPS_NS16550_SHIFT)
+#define UART_LSR_OFS   (UART_LSR << CONFIG_MIPS_CPS_NS16550_SHIFT)
+
+/**
+ * _mips_cps_putc() - write a character to the UART
+ * @a0: ASCII character to write
+ * @t9: UART base address
+ */
+LEAF(_mips_cps_putc)
+1:     lw              t0, UART_LSR_OFS(t9)
+       andi            t0, t0, UART_LSR_TEMT
+       beqz            t0, 1b
+       sb              a0, UART_TX_OFS(t9)
+       jr              ra
+       END(_mips_cps_putc)
+
+/**
+ * _mips_cps_puts() - write a string to the UART
+ * @a0: pointer to NULL-terminated ASCII string
+ * @t9: UART base address
+ *
+ * Write a null-terminated ASCII string to the UART.
+ */
+NESTED(_mips_cps_puts, 0, ra)
+       move            s7, ra
+       move            s6, a0
+
+1:     lb              a0, 0(s6)
+       beqz            a0, 2f
+       jal             _mips_cps_putc
+       PTR_ADDIU       s6, s6, 1
+       b               1b
+
+2:     jr              s7
+       END(_mips_cps_puts)
+
+/**
+ * _mips_cps_putx4 - write a 4b hex value to the UART
+ * @a0: the 4b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a single hexadecimal character to the UART.
+ */
+NESTED(_mips_cps_putx4, 0, ra)
+       andi            a0, a0, 0xf
+       li              t0, '0'
+       blt             a0, 10, 1f
+       li              t0, 'a'
+       addiu           a0, a0, -10
+1:     addu            a0, a0, t0
+       b               _mips_cps_putc
+       END(_mips_cps_putx4)
+
+/**
+ * _mips_cps_putx8 - write an 8b hex value to the UART
+ * @a0: the 8b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write an 8 bit value (ie. 2 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx8, 0, ra)
+       move            s3, ra
+       move            s2, a0
+       srl             a0, a0, 4
+       jal             _mips_cps_putx4
+       move            a0, s2
+       move            ra, s3
+       b               _mips_cps_putx4
+       END(_mips_cps_putx8)
+
+/**
+ * _mips_cps_putx16 - write a 16b hex value to the UART
+ * @a0: the 16b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 16 bit value (ie. 4 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx16, 0, ra)
+       move            s5, ra
+       move            s4, a0
+       srl             a0, a0, 8
+       jal             _mips_cps_putx8
+       move            a0, s4
+       move            ra, s5
+       b               _mips_cps_putx8
+       END(_mips_cps_putx16)
+
+/**
+ * _mips_cps_putx32 - write a 32b hex value to the UART
+ * @a0: the 32b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 32 bit value (ie. 8 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx32, 0, ra)
+       move            s7, ra
+       move            s6, a0
+       srl             a0, a0, 16
+       jal             _mips_cps_putx16
+       move            a0, s6
+       move            ra, s7
+       b               _mips_cps_putx16
+       END(_mips_cps_putx32)
+
+#ifdef CONFIG_64BIT
+
+/**
+ * _mips_cps_putx64 - write a 64b hex value to the UART
+ * @a0: the 64b value to write to the UART
+ * @t9: UART base address
+ *
+ * Write a 64 bit value (ie. 16 hexadecimal characters) to the UART.
+ */
+NESTED(_mips_cps_putx64, 0, ra)
+       move            sp, ra
+       move            s8, a0
+       dsrl32          a0, a0, 0
+       jal             _mips_cps_putx32
+       move            a0, s8
+       move            ra, sp
+       b               _mips_cps_putx32
+       END(_mips_cps_putx64)
+
+#define _mips_cps_putxlong _mips_cps_putx64
+
+#else /* !CONFIG_64BIT */
+
+#define _mips_cps_putxlong _mips_cps_putx32
+
+#endif /* !CONFIG_64BIT */
+
+/**
+ * mips_cps_bev_dump() - dump relevant exception state to UART
+ * @a0: pointer to NULL-terminated ASCII string naming the exception
+ *
+ * Write information that may be useful in debugging an exception to the
+ * UART configured by CONFIG_MIPS_CPS_NS16550_*. As this BEV exception
+ * will only be run if something goes horribly wrong very early during
+ * the bringup of a core and it is very likely to be unsafe to perform
+ * memory accesses at that point (cache state indeterminate, EVA may not
+ * be configured, coherence may be disabled) let alone have a stack,
+ * this is all written in assembly using only registers & unmapped
+ * uncached access to the UART registers.
+ */
+LEAF(mips_cps_bev_dump)
+       move            s0, ra
+       move            s1, a0
+
+       li              t9, CKSEG1ADDR(CONFIG_MIPS_CPS_NS16550_BASE)
+
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_bev
+       jal             _mips_cps_puts
+       move            a0, s1
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+
+#define DUMP_COP0_REG(reg, name, sz, _mfc0)            \
+       PTR_LA          a0, 8f;                         \
+       jal             _mips_cps_puts;                 \
+       _mfc0           a0, reg;                        \
+       jal             _mips_cps_putx##sz;             \
+       PTR_LA          a0, str_newline;                \
+       jal             _mips_cps_puts;                 \
+       TEXT(name)
+
+       DUMP_COP0_REG(CP0_CAUSE,    "Cause:    0x", 32, mfc0)
+       DUMP_COP0_REG(CP0_STATUS,   "Status:   0x", 32, mfc0)
+       DUMP_COP0_REG(CP0_EBASE,    "EBase:    0x", long, MFC0)
+       DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", long, MFC0)
+       DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 32, mfc0)
+
+       PTR_LA          a0, str_newline
+       jal             _mips_cps_puts
+       jr              s0
+       END(mips_cps_bev_dump)
+
+.pushsection   .data
+str_bev: .asciiz "BEV Exception: "
+str_newline: .asciiz "\r\n"
+.popsection
index 209ded16806bf5a295ff202258f5b7ff42070940..8fd5a276cad23493f6500d0f4b01515ee20062f5 100644 (file)
 
 .set noreorder
 
+#ifdef CONFIG_64BIT
+# define STATUS_BITDEPS                ST0_KX
+#else
+# define STATUS_BITDEPS                0
+#endif
+
+#ifdef CONFIG_MIPS_CPS_NS16550
+
+#define DUMP_EXCEP(name)               \
+       PTR_LA  a0, 8f;                 \
+       jal     mips_cps_bev_dump;      \
+        nop;                           \
+       TEXT(name)
+
+#else /* !CONFIG_MIPS_CPS_NS16550 */
+
+#define DUMP_EXCEP(name)
+
+#endif /* !CONFIG_MIPS_CPS_NS16550 */
+
        /*
         * Set dest to non-zero if the core supports the MT ASE, else zero. If
         * MT is not supported then branch to nomt.
         */
        .macro  has_mt  dest, nomt
-       mfc0    \dest, CP0_CONFIG
-       bgez    \dest, \nomt
-        mfc0   \dest, CP0_CONFIG, 1
+       mfc0    \dest, CP0_CONFIG, 1
        bgez    \dest, \nomt
         mfc0   \dest, CP0_CONFIG, 2
        bgez    \dest, \nomt
 
 LEAF(mips_cps_core_entry)
        /*
-        * These first 12 bytes will be patched by cps_smp_setup to load the
-        * base address of the CM GCRs into register v1 and the CCA to use into
-        * register s0.
+        * These first 4 bytes will be patched by cps_smp_setup to load the
+        * CCA to use into register s0.
         */
-       .quad   0
        .word   0
 
        /* Check whether we're here due to an NMI */
@@ -71,7 +87,7 @@ not_nmi:
        mtc0    t0, CP0_CAUSE
 
        /* Setup Status */
-       li      t0, ST0_CU1 | ST0_CU0
+       li      t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
        mtc0    t0, CP0_STATUS
 
        /*
@@ -151,6 +167,12 @@ dcache_done:
        mtc0    t0, CP0_CONFIG
        ehb
 
+       /* Calculate an uncached address for the CM GCRs */
+       MFC0    v1, CP0_CMGCRBASE
+       PTR_SLL v1, v1, 4
+       PTR_LI  t0, UNCAC_BASE
+       PTR_ADDU v1, v1, t0
+
        /* Enter the coherent domain */
        li      t0, 0xff
        sw      t0, GCR_CL_COHERENCE_OFS(v1)
@@ -188,36 +210,42 @@ dcache_done:
 
 .org 0x200
 LEAF(excep_tlbfill)
+       DUMP_EXCEP("TLB Fill")
        b       .
         nop
        END(excep_tlbfill)
 
 .org 0x280
 LEAF(excep_xtlbfill)
+       DUMP_EXCEP("XTLB Fill")
        b       .
         nop
        END(excep_xtlbfill)
 
 .org 0x300
 LEAF(excep_cache)
+       DUMP_EXCEP("Cache")
        b       .
         nop
        END(excep_cache)
 
 .org 0x380
 LEAF(excep_genex)
+       DUMP_EXCEP("General")
        b       .
         nop
        END(excep_genex)
 
 .org 0x400
 LEAF(excep_intex)
+       DUMP_EXCEP("Interrupt")
        b       .
         nop
        END(excep_intex)
 
 .org 0x480
 LEAF(excep_ejtag)
+       DUMP_EXCEP("EJTAG")
        PTR_LA  k0, ejtag_debug_handler
        jr      k0
         nop
index 09a51d091941be3aa75ae37b53b386714a6d3db5..6b9064499bd3dfb49ef0c09ad3da48034dea0ff2 100644 (file)
@@ -536,8 +536,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
                c->options |= MIPS_CPU_SEGMENTS;
        if (config3 & MIPS_CONF3_MSA)
                c->ases |= MIPS_ASE_MSA;
-       /* Only tested on 32-bit cores */
-       if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT)) {
+       if (config3 & MIPS_CONF3_PW) {
                c->htw_seq = 0;
                c->options |= MIPS_CPU_HTW;
        }
index e5ed7ada14334c682218aa567e18414465fea81c..1f910563fdf60b3be0b4dcdca024837638818bf8 100644 (file)
@@ -28,6 +28,43 @@ static u64 notrace r4k_read_sched_clock(void)
        return read_c0_count();
 }
 
+static inline unsigned int rdhwr_count(void)
+{
+       unsigned int count;
+
+       __asm__ __volatile__(
+       "       .set push\n"
+       "       .set mips32r2\n"
+       "       rdhwr   %0, $2\n"
+       "       .set pop\n"
+       : "=r" (count));
+
+       return count;
+}
+
+static bool rdhwr_count_usable(void)
+{
+       unsigned int prev, curr, i;
+
+       /*
+        * Older QEMUs have a broken implementation of RDHWR for the CP0 count
+        * which always returns a constant value. Try to identify this and don't
+        * use it in the VDSO if it is broken. This workaround can be removed
+        * once the fix has been in QEMU stable for a reasonable amount of time.
+        */
+       for (i = 0, prev = rdhwr_count(); i < 100; i++) {
+               curr = rdhwr_count();
+
+               if (curr != prev)
+                       return true;
+
+               prev = curr;
+       }
+
+       pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n");
+       return false;
+}
+
 int __init init_r4k_clocksource(void)
 {
        if (!cpu_has_counter || !mips_hpt_frequency)
@@ -36,6 +73,13 @@ int __init init_r4k_clocksource(void)
        /* Calculate a somewhat reasonable rating value */
        clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
 
+       /*
+        * R2 onwards makes the count accessible to user mode so it can be used
+        * by the VDSO (HWREna is configured by configure_hwrena()).
+        */
+       if (cpu_has_mips_r2_r6 && rdhwr_count_usable())
+               clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K;
+
        clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
 
        sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
index ab1478d5a4db1b247caa94527925da0d005adf10..46794d64c0bfe3f9779cc43714cc7c3fbb6a10bc 100644 (file)
@@ -134,6 +134,16 @@ void __init check_wait(void)
                return;
        }
 
+       /*
+        * MIPSr6 specifies that masked interrupts should unblock an executing
+        * wait instruction, and thus that it is safe for us to use
+        * r4k_wait_irqoff. Yippee!
+        */
+       if (cpu_has_mips_r6) {
+               cpu_wait = r4k_wait_irqoff;
+               return;
+       }
+
        switch (current_cpu_type()) {
        case CPU_R3081:
        case CPU_R3081E:
@@ -155,12 +165,12 @@ void __init check_wait(void)
        case CPU_4KEC:
        case CPU_4KSC:
        case CPU_5KC:
+       case CPU_5KE:
        case CPU_25KF:
        case CPU_PR4450:
        case CPU_BMIPS3300:
        case CPU_BMIPS4350:
        case CPU_BMIPS4380:
-       case CPU_BMIPS5000:
        case CPU_CAVIUM_OCTEON:
        case CPU_CAVIUM_OCTEON_PLUS:
        case CPU_CAVIUM_OCTEON2:
@@ -171,7 +181,9 @@ void __init check_wait(void)
        case CPU_XLP:
                cpu_wait = r4k_wait;
                break;
-
+       case CPU_BMIPS5000:
+               cpu_wait = r4k_wait_irqoff;
+               break;
        case CPU_RM7000:
                cpu_wait = rm7k_wait_irqoff;
                break;
@@ -196,7 +208,6 @@ void __init check_wait(void)
        case CPU_INTERAPTIV:
        case CPU_M5150:
        case CPU_QEMU_GENERIC:
-       case CPU_I6400:
                cpu_wait = r4k_wait;
                if (read_c0_config7() & MIPS_CONF7_WII)
                        cpu_wait = r4k_wait_irqoff;
index b8ceee576cdfce2e22e1b2d8ffab6f90bf69f6b8..1448c1f43d4e4ae6657b819a5c8ee238a7332e34 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <linux/errno.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
 
 #include <asm/mips-cm.h>
 #include <asm/mipsregs.h>
@@ -136,6 +138,9 @@ static char *cm3_causes[32] = {
        "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
 };
 
+static DEFINE_PER_CPU_ALIGNED(spinlock_t, cm_core_lock);
+static DEFINE_PER_CPU_ALIGNED(unsigned long, cm_core_lock_flags);
+
 phys_addr_t __mips_cm_phys_base(void)
 {
        u32 config3 = read_c0_config3();
@@ -200,6 +205,7 @@ int mips_cm_probe(void)
 {
        phys_addr_t addr;
        u32 base_reg;
+       unsigned cpu;
 
        /*
         * No need to probe again if we have already been
@@ -247,38 +253,70 @@ int mips_cm_probe(void)
        /* determine register width for this CM */
        mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
 
+       for_each_possible_cpu(cpu)
+               spin_lock_init(&per_cpu(cm_core_lock, cpu));
+
        return 0;
 }
 
-void mips_cm_error_report(void)
+void mips_cm_lock_other(unsigned int core, unsigned int vp)
 {
-       unsigned long revision = mips_cm_revision();
+       unsigned curr_core;
+       u32 val;
+
+       preempt_disable();
+       curr_core = current_cpu_data.core;
+       spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
+                         per_cpu(cm_core_lock_flags, curr_core));
+
+       if (mips_cm_revision() >= CM_REV_CM3) {
+               val = core << CM3_GCR_Cx_OTHER_CORE_SHF;
+               val |= vp << CM3_GCR_Cx_OTHER_VP_SHF;
+       } else {
+               BUG_ON(vp != 0);
+               val = core << CM_GCR_Cx_OTHER_CORENUM_SHF;
+       }
+
+       write_gcr_cl_other(val);
+
        /*
-        * CM3 has a 64-bit Error cause register with 0:57 containing the error
-        * info and 63:58 the error type. For old CMs, everything is contained
-        * in a single 32-bit register (0:26 and 31:27 respectively). Even
-        * though the cm_error is u64, we will simply ignore the upper word
-        * for CM2.
+        * Ensure the core-other region reflects the appropriate core &
+        * VP before any accesses to it occur.
         */
-       u64 cm_error = read_gcr_error_cause();
-       int cm_error_cause_sft = CM_GCR_ERROR_CAUSE_ERRTYPE_SHF +
-                                ((revision >= CM_REV_CM3) ? 31 : 0);
-       unsigned long cm_addr = read_gcr_error_addr();
-       unsigned long cm_other = read_gcr_error_mult();
+       mb();
+}
+
+void mips_cm_unlock_other(void)
+{
+       unsigned curr_core = current_cpu_data.core;
+
+       spin_unlock_irqrestore(&per_cpu(cm_core_lock, curr_core),
+                              per_cpu(cm_core_lock_flags, curr_core));
+       preempt_enable();
+}
+
+void mips_cm_error_report(void)
+{
+       u64 cm_error, cm_addr, cm_other;
+       unsigned long revision;
        int ocause, cause;
        char buf[256];
 
        if (!mips_cm_present())
                return;
 
-       cause = cm_error >> cm_error_cause_sft;
+       revision = mips_cm_revision();
 
-       if (!cause)
-               /* All good */
-               return;
-
-       ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
        if (revision < CM_REV_CM3) { /* CM2 */
+               cm_error = read_gcr_error_cause();
+               cm_addr = read_gcr_error_addr();
+               cm_other = read_gcr_error_mult();
+               cause = cm_error >> CM_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+               ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+               if (!cause)
+                       return;
+
                if (cause < 16) {
                        unsigned long cca_bits = (cm_error >> 15) & 7;
                        unsigned long tr_bits = (cm_error >> 12) & 7;
@@ -310,18 +348,30 @@ void mips_cm_error_report(void)
                }
                        pr_err("CM_ERROR=%08llx %s <%s>\n", cm_error,
                               cm2_causes[cause], buf);
-               pr_err("CM_ADDR =%08lx\n", cm_addr);
-               pr_err("CM_OTHER=%08lx %s\n", cm_other, cm2_causes[ocause]);
+               pr_err("CM_ADDR =%08llx\n", cm_addr);
+               pr_err("CM_OTHER=%08llx %s\n", cm_other, cm2_causes[ocause]);
        } else { /* CM3 */
-       /* Used by cause == {1,2,3} */
-               unsigned long core_id_bits = (cm_error >> 22) & 0xf;
-               unsigned long vp_id_bits = (cm_error >> 18) & 0xf;
-               unsigned long cmd_bits = (cm_error >> 14) & 0xf;
-               unsigned long cmd_group_bits = (cm_error >> 11) & 0xf;
-               unsigned long cm3_cca_bits = (cm_error >> 8) & 7;
-               unsigned long mcp_bits = (cm_error >> 5) & 0xf;
-               unsigned long cm3_tr_bits = (cm_error >> 1) & 0xf;
-               unsigned long sched_bit = cm_error & 0x1;
+               ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
+               ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
+
+               cm_error = read64_gcr_error_cause();
+               cm_addr = read64_gcr_error_addr();
+               cm_other = read64_gcr_error_mult();
+               cause = cm_error >> CM3_GCR_ERROR_CAUSE_ERRTYPE_SHF;
+               ocause = cm_other >> CM_GCR_ERROR_MULT_ERR2ND_SHF;
+
+               if (!cause)
+                       return;
+
+               /* Used by cause == {1,2,3} */
+               core_id_bits = (cm_error >> 22) & 0xf;
+               vp_id_bits = (cm_error >> 18) & 0xf;
+               cmd_bits = (cm_error >> 14) & 0xf;
+               cmd_group_bits = (cm_error >> 11) & 0xf;
+               cm3_cca_bits = (cm_error >> 8) & 7;
+               mcp_bits = (cm_error >> 5) & 0xf;
+               cm3_tr_bits = (cm_error >> 1) & 0xf;
+               sched_bit = cm_error & 0x1;
 
                if (cause == 1 || cause == 3) { /* Tag ECC */
                        unsigned long tag_ecc = (cm_error >> 57) & 0x1;
@@ -363,12 +413,14 @@ void mips_cm_error_report(void)
                                 cm3_cmd_group[cmd_group_bits],
                                 cm3_cca_bits, 1 << mcp_bits,
                                 cm3_tr[cm3_tr_bits], sched_bit);
+               } else {
+                       buf[0] = 0;
                }
 
                pr_err("CM_ERROR=%llx %s <%s>\n", cm_error,
                       cm3_causes[cause], buf);
-               pr_err("CM_ADDR =%lx\n", cm_addr);
-               pr_err("CM_OTHER=%lx %s\n", cm_other, cm3_causes[ocause]);
+               pr_err("CM_ADDR =%llx\n", cm_addr);
+               pr_err("CM_OTHER=%llx %s\n", cm_other, cm3_causes[ocause]);
        }
 
        /* reprime cause register */
index 8af4d627b68b96d0d998ee7c4a06176af8234138..566b8d2c092c31de6293f245d81b12a899d40622 100644 (file)
@@ -76,6 +76,12 @@ void mips_cpc_lock_other(unsigned int core)
        spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core),
                          per_cpu(cpc_core_lock_flags, curr_core));
        write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF);
+
+       /*
+        * Ensure the core-other region reflects the appropriate core &
+        * VP before any accesses to it occur.
+        */
+       mb();
 }
 
 void mips_cpc_unlock_other(void)
index f2977f00911b303177fe086f72c0ae6be4a39313..1f5aac7f9ec3588ec3c48a563b057351b1abfe18 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/break.h>
+#include <asm/debug.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
@@ -2363,7 +2364,6 @@ static const struct file_operations mipsr2_clear_fops = {
 
 static int __init mipsr2_init_debugfs(void)
 {
-       extern struct dentry    *mips_debugfs_dir;
        struct dentry           *mipsr2_emul;
 
        if (!mips_debugfs_dir)
index 076ead2a985948e145864a17a506b2ff3a93bc31..87bc74a5a518c5fca349104a6257a2ea6242710c 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <asm/cpu.h>
+#include <asm/debug.h>
 #include <asm/mipsregs.h>
 
 static void build_segment_config(char *str, unsigned int cfg)
@@ -91,7 +92,6 @@ static const struct file_operations segments_fops = {
 
 static int __init segments_info(void)
 {
-       extern struct dentry *mips_debugfs_dir;
        struct dentry *segments;
 
        if (cpu_has_segments) {
index 479515109e5badec96942ee594e3a450ab011f11..66aac55df3497f79d39f1b203601eccf3a25a48f 100644 (file)
 #include <asm/cache.h>
 #include <asm/cdmm.h>
 #include <asm/cpu.h>
+#include <asm/debug.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
 #include <asm/prom.h>
 
+#ifdef CONFIG_MIPS_ELF_APPENDED_DTB
+const char __section(.appended_dtb) __appended_dtb[0x100000];
+#endif /* CONFIG_MIPS_ELF_APPENDED_DTB */
+
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
@@ -616,6 +621,10 @@ static void __init request_crashkernel(struct resource *res)
 }
 #endif /* !defined(CONFIG_KEXEC)  */
 
+#define USE_PROM_CMDLINE       IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
+#define USE_DTB_CMDLINE                IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
+#define EXTEND_WITH_PROM       IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND)
+
 static void __init arch_mem_init(char **cmdline_p)
 {
        struct memblock_region *reg;
@@ -640,18 +649,24 @@ static void __init arch_mem_init(char **cmdline_p)
        pr_info("Determined physical RAM map:\n");
        print_memory_map();
 
-#ifdef CONFIG_CMDLINE_BOOL
-#ifdef CONFIG_CMDLINE_OVERRIDE
+#if defined(CONFIG_CMDLINE_BOOL) && defined(CONFIG_CMDLINE_OVERRIDE)
        strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
 #else
+       if ((USE_PROM_CMDLINE && arcs_cmdline[0]) ||
+           (USE_DTB_CMDLINE && !boot_command_line[0]))
+               strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+
+       if (EXTEND_WITH_PROM && arcs_cmdline[0]) {
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+       }
+
+#if defined(CONFIG_CMDLINE_BOOL)
        if (builtin_cmdline[0]) {
-               strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
-               strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
        }
-       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 #endif
-#else
-       strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 #endif
        strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 
index 2fec67bfc457cc969056f6f46258c0f00992be83..bf792e2839a6f31b5cde496cb84892ded60d5b5f 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/ucontext.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 #include <asm/dsp.h>
 #include <asm/inst.h>
 #include <asm/msa.h>
@@ -752,16 +751,15 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
 struct mips_abi mips_abi = {
 #ifdef CONFIG_TRAD_SIGNALS
        .setup_frame    = setup_frame,
-       .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
 #endif
        .setup_rt_frame = setup_rt_frame,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, rt_signal_trampoline),
        .restart        = __NR_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+       .vdso           = &vdso_image,
 };
 
 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
@@ -801,11 +799,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
        }
 
        if (sig_uses_siginfo(&ksig->ka))
-               ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
+               ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
                                          ksig, regs, oldset);
        else
-               ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
-                                      regs, oldset);
+               ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn,
+                                      ksig, regs, oldset);
 
        signal_setup_done(ret, ksig, 0);
 }
index f7e89524e3166fc23b0ea7ae08c10137d75de74e..4909639aa35ba7fcb3de868c4c28ca92e8f7a54e 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/ucontext.h>
 #include <asm/fpu.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 #include <asm/dsp.h>
 
 #include "signal-common.h"
@@ -406,14 +405,12 @@ static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
  */
 struct mips_abi mips_abi_32 = {
        .setup_frame    = setup_frame_32,
-       .signal_return_offset =
-               offsetof(struct mips_vdso, o32_signal_trampoline),
        .setup_rt_frame = setup_rt_frame_32,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, o32_rt_signal_trampoline),
        .restart        = __NR_O32_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
+
+       .vdso           = &vdso_image_o32,
 };
index 0d017fdcaf07aa50c583e644f4dc1f21d9ab80ee..a7bc384305008ece50b78c9ff72364e54c7af2e5 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
 #include <asm/war.h>
-#include <asm/vdso.h>
 
 #include "signal-common.h"
 
@@ -151,11 +150,11 @@ static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
 
 struct mips_abi mips_abi_n32 = {
        .setup_rt_frame = setup_rt_frame_n32,
-       .rt_signal_return_offset =
-               offsetof(struct mips_vdso, n32_rt_signal_trampoline),
        .restart        = __NR_N32_restart_syscall,
 
        .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs),
        .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr),
        .off_sc_used_math = offsetof(struct sigcontext, sc_used_math),
+
+       .vdso           = &vdso_image_n32,
 };
index c88937745b4ea18c7faf699f936f00cd42f9372d..e04c8057b88238956efe64c519dfa3aac41e1ba9 100644 (file)
@@ -8,6 +8,7 @@
  * option) any later version.
  */
 
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irqchip/mips-gic.h>
 #include <linux/sched.h>
@@ -37,8 +38,9 @@ static unsigned core_vpe_count(unsigned core)
        if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
                return 1;
 
-       write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+       mips_cm_lock_other(core, 0);
        cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK;
+       mips_cm_unlock_other();
        return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1;
 }
 
@@ -133,11 +135,9 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
        /*
         * Patch the start of mips_cps_core_entry to provide:
         *
-        * v1 = CM base address
         * s0 = kseg0 CCA
         */
        entry_code = (u32 *)&mips_cps_core_entry;
-       UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
        uasm_i_addiu(&entry_code, 16, 0, cca);
        blast_dcache_range((unsigned long)&mips_cps_core_entry,
                           (unsigned long)entry_code);
@@ -190,10 +190,11 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
 
 static void boot_core(unsigned core)
 {
-       u32 access;
+       u32 access, stat, seq_state;
+       unsigned timeout;
 
        /* Select the appropriate core */
-       write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF);
+       mips_cm_lock_other(core, 0);
 
        /* Set its reset vector */
        write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry));
@@ -210,12 +211,36 @@ static void boot_core(unsigned core)
                /* Reset the core */
                mips_cpc_lock_other(core);
                write_cpc_co_cmd(CPC_Cx_CMD_RESET);
+
+               timeout = 100;
+               while (true) {
+                       stat = read_cpc_co_stat_conf();
+                       seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE_MSK;
+
+                       /* U6 == coherent execution, ie. the core is up */
+                       if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U6)
+                               break;
+
+                       /* Delay a little while before we start warning */
+                       if (timeout) {
+                               timeout--;
+                               mdelay(10);
+                               continue;
+                       }
+
+                       pr_warn("Waiting for core %u to start... STAT_CONF=0x%x\n",
+                               core, stat);
+                       mdelay(1000);
+               }
+
                mips_cpc_unlock_other();
        } else {
                /* Take the core out of reset */
                write_gcr_co_reset_release(0);
        }
 
+       mips_cm_unlock_other();
+
        /* The core is now powered up */
        bitmap_set(core_power, core, 1);
 }
index 5f0ab5bcd01edc5e454a3d534a996f6ed03697de..9b63829cf929408f3f75054478d6d3e637ff0c99 100644 (file)
@@ -46,9 +46,11 @@ void gic_send_ipi_single(int cpu, unsigned int action)
 
        if (mips_cpc_present() && (core != current_cpu_data.core)) {
                while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+                       mips_cm_lock_other(core, 0);
                        mips_cpc_lock_other(core);
                        write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
                        mips_cpc_unlock_other();
+                       mips_cm_unlock_other();
                }
        }
 
index 39f7ab7b04269b6a22b3573fc3f2bc377605d088..f7d86955d1b80b43b4321e1314ea6ceede4224f4 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/debugfs.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
-
+#include <asm/debug.h>
 
 static int ss_get(void *data, u64 *val)
 {
@@ -115,8 +115,6 @@ static int multi_get(void *data, u64 *val)
 
 DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
 
-
-extern struct dentry *mips_debugfs_dir;
 static int __init spinlock_test(void)
 {
        struct dentry *d;
index 1ba775d24d38f890d4e29a2168b533870d7cfb8b..506021f62549d98c7bc8260b300c659fd0118834 100644 (file)
  * Save stack-backtrace addresses into a stack_trace buffer:
  */
 static void save_raw_context_stack(struct stack_trace *trace,
-       unsigned long reg29)
+       unsigned long reg29, int savesched)
 {
        unsigned long *sp = (unsigned long *)reg29;
        unsigned long addr;
 
        while (!kstack_end(sp)) {
                addr = *sp++;
-               if (__kernel_text_address(addr)) {
+               if (__kernel_text_address(addr) &&
+                   (savesched || !in_sched_functions(addr))) {
                        if (trace->skip > 0)
                                trace->skip--;
                        else
@@ -31,7 +32,7 @@ static void save_raw_context_stack(struct stack_trace *trace,
 }
 
 static void save_context_stack(struct stack_trace *trace,
-       struct task_struct *tsk, struct pt_regs *regs)
+       struct task_struct *tsk, struct pt_regs *regs, int savesched)
 {
        unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
@@ -43,20 +44,22 @@ static void save_context_stack(struct stack_trace *trace,
                        (unsigned long)task_stack_page(tsk);
                if (stack_page && sp >= stack_page &&
                    sp <= stack_page + THREAD_SIZE - 32)
-                       save_raw_context_stack(trace, sp);
+                       save_raw_context_stack(trace, sp, savesched);
                return;
        }
        do {
-               if (trace->skip > 0)
-                       trace->skip--;
-               else
-                       trace->entries[trace->nr_entries++] = pc;
-               if (trace->nr_entries >= trace->max_entries)
-                       break;
+               if (savesched || !in_sched_functions(pc)) {
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = pc;
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
                pc = unwind_stack(tsk, &sp, pc, &ra);
        } while (pc);
 #else
-       save_raw_context_stack(trace, sp);
+       save_raw_context_stack(trace, sp, savesched);
 #endif
 }
 
@@ -82,6 +85,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
                regs->cp0_epc = tsk->thread.reg31;
        } else
                prepare_frametrace(regs);
-       save_context_stack(trace, tsk, regs);
+       save_context_stack(trace, tsk, regs, tsk == current);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index fdb392b27e8109f8b02a1b09b3a3d95cdbd20f14..886cb1976e90f682dafac7a958043d68bc4b6473 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/irq.h>
 #include <linux/perf_event.h>
 
+#include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
 #include <asm/break.h>
@@ -1856,12 +1857,14 @@ void __noreturn nmi_exception_handler(struct pt_regs *regs)
 {
        char str[100];
 
+       nmi_enter();
        raw_notifier_call_chain(&nmi_chain, 0, regs);
        bust_spinlocks(1);
        snprintf(str, 100, "CPU%d NMI taken, CP0_EPC=%lx\n",
                 smp_processor_id(), regs->cp0_epc);
        regs->cp0_epc = read_c0_errorepc();
        die(str, regs);
+       nmi_exit();
 }
 
 #define VECTORSPACING 0x100    /* for EI/VI mode */
@@ -2204,12 +2207,8 @@ void __init trap_init(void)
                ebase = (unsigned long)
                        __alloc_bootmem(size, 1 << fls(size), 0);
        } else {
-#ifdef CONFIG_KVM_GUEST
-#define KVM_GUEST_KSEG0     0x40000000
-        ebase = KVM_GUEST_KSEG0;
-#else
-        ebase = CKSEG0;
-#endif
+               ebase = CAC_BASE;
+
                if (cpu_has_mips_r2_r6)
                        ebase += (read_c0_ebase() & 0x3ffff000);
        }
index 990354dd6bdedb79d77d8ec4291e14e3836dcba3..490cea569d57d0088e50e241f3465c91f07bbcc7 100644 (file)
@@ -85,6 +85,7 @@
 #include <asm/branch.h>
 #include <asm/byteorder.h>
 #include <asm/cop2.h>
+#include <asm/debug.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
@@ -2295,7 +2296,6 @@ asmlinkage void do_ade(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_DEBUG_FS
-extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_unaligned(void)
 {
        struct dentry *d;
index ed2a278722a9599e9edfaf501bda7f88b66690f7..975e99759bab9ec1ae6aa80a47fa2f97765efcc6 100644 (file)
 /*
- * 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) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
  *
- * Copyright (C) 2009, 2010 Cavium Networks, Inc.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
  */
 
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/unistd.h>
-#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
 
+#include <asm/abi.h>
 #include <asm/vdso.h>
-#include <asm/uasm.h>
-#include <asm/processor.h>
+
+/* Kernel-provided data used by the VDSO. */
+static union mips_vdso_data vdso_data __page_aligned_data;
 
 /*
- * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
+ * what we map and where within the area they are mapped is determined at
+ * runtime.
  */
-#define __NR_O32_sigreturn             4119
-#define __NR_O32_rt_sigreturn          4193
-#define __NR_N32_rt_sigreturn          6211
+static struct page *no_pages[] = { NULL };
+static struct vm_special_mapping vdso_vvar_mapping = {
+       .name = "[vvar]",
+       .pages = no_pages,
+};
 
-static struct page *vdso_page;
-
-static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
+static void __init init_vdso_image(struct mips_vdso_image *image)
 {
-       uasm_i_addiu(&tramp, 2, 0, sigreturn);  /* li v0, sigreturn */
-       uasm_i_syscall(&tramp, 0);
+       unsigned long num_pages, i;
+
+       BUG_ON(!PAGE_ALIGNED(image->data));
+       BUG_ON(!PAGE_ALIGNED(image->size));
+
+       num_pages = image->size / PAGE_SIZE;
+
+       for (i = 0; i < num_pages; i++) {
+               image->mapping.pages[i] =
+                       virt_to_page(image->data + (i * PAGE_SIZE));
+       }
 }
 
 static int __init init_vdso(void)
 {
-       struct mips_vdso *vdso;
-
-       vdso_page = alloc_page(GFP_KERNEL);
-       if (!vdso_page)
-               panic("Cannot allocate vdso");
-
-       vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
-       if (!vdso)
-               panic("Cannot map vdso");
-       clear_page(vdso);
-
-       install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
-#ifdef CONFIG_32BIT
-       install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
-#else
-       install_trampoline(vdso->n32_rt_signal_trampoline,
-                          __NR_N32_rt_sigreturn);
-       install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
-       install_trampoline(vdso->o32_rt_signal_trampoline,
-                          __NR_O32_rt_sigreturn);
+       init_vdso_image(&vdso_image);
+
+#ifdef CONFIG_MIPS32_O32
+       init_vdso_image(&vdso_image_o32);
 #endif
 
-       vunmap(vdso);
+#ifdef CONFIG_MIPS32_N32
+       init_vdso_image(&vdso_image_n32);
+#endif
 
        return 0;
 }
 subsys_initcall(init_vdso);
 
-static unsigned long vdso_addr(unsigned long start)
+void update_vsyscall(struct timekeeper *tk)
 {
-       unsigned long offset = 0UL;
-
-       if (current->flags & PF_RANDOMIZE) {
-               offset = get_random_int();
-               offset <<= PAGE_SHIFT;
-               if (TASK_IS_32BIT_ADDR)
-                       offset &= 0xfffffful;
-               else
-                       offset &= 0xffffffful;
+       vdso_data_write_begin(&vdso_data);
+
+       vdso_data.xtime_sec = tk->xtime_sec;
+       vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec;
+       vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec;
+       vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec;
+       vdso_data.cs_shift = tk->tkr_mono.shift;
+
+       vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode;
+       if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+               vdso_data.cs_mult = tk->tkr_mono.mult;
+               vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last;
+               vdso_data.cs_mask = tk->tkr_mono.mask;
        }
 
-       return STACK_TOP + offset;
+       vdso_data_write_end(&vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+       if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+               vdso_data.tz_minuteswest = sys_tz.tz_minuteswest;
+               vdso_data.tz_dsttime = sys_tz.tz_dsttime;
+       }
 }
 
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
-       int ret;
-       unsigned long addr;
+       struct mips_vdso_image *image = current->thread.abi->vdso;
        struct mm_struct *mm = current->mm;
+       unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
+       struct vm_area_struct *vma;
+       struct resource gic_res;
+       int ret;
 
        down_write(&mm->mmap_sem);
 
-       addr = vdso_addr(mm->start_stack);
+       /*
+        * Determine total area size. This includes the VDSO data itself, the
+        * data page, and the GIC user page if present. Always create a mapping
+        * for the GIC user area if the GIC is present regardless of whether it
+        * is the current clocksource, in case it comes into use later on. We
+        * only map a page even though the total area is 64K, as we only need
+        * the counter registers at the start.
+        */
+       gic_size = gic_present ? PAGE_SIZE : 0;
+       vvar_size = gic_size + PAGE_SIZE;
+       size = vvar_size + image->size;
+
+       base = get_unmapped_area(NULL, 0, size, 0, 0);
+       if (IS_ERR_VALUE(base)) {
+               ret = base;
+               goto out;
+       }
+
+       data_addr = base + gic_size;
+       vdso_addr = data_addr + PAGE_SIZE;
 
-       addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
-       if (IS_ERR_VALUE(addr)) {
-               ret = addr;
-               goto up_fail;
+       vma = _install_special_mapping(mm, base, vvar_size,
+                                      VM_READ | VM_MAYREAD,
+                                      &vdso_vvar_mapping);
+       if (IS_ERR(vma)) {
+               ret = PTR_ERR(vma);
+               goto out;
        }
 
-       ret = install_special_mapping(mm, addr, PAGE_SIZE,
-                                     VM_READ|VM_EXEC|
-                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-                                     &vdso_page);
+       /* Map GIC user page. */
+       if (gic_size) {
+               ret = gic_get_usm_range(&gic_res);
+               if (ret)
+                       goto out;
+
+               ret = io_remap_pfn_range(vma, base,
+                                        gic_res.start >> PAGE_SHIFT,
+                                        gic_size,
+                                        pgprot_noncached(PAGE_READONLY));
+               if (ret)
+                       goto out;
+       }
 
+       /* Map data page. */
+       ret = remap_pfn_range(vma, data_addr,
+                             virt_to_phys(&vdso_data) >> PAGE_SHIFT,
+                             PAGE_SIZE, PAGE_READONLY);
        if (ret)
-               goto up_fail;
+               goto out;
+
+       /* Map VDSO image. */
+       vma = _install_special_mapping(mm, vdso_addr, image->size,
+                                      VM_READ | VM_EXEC |
+                                      VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+                                      &image->mapping);
+       if (IS_ERR(vma)) {
+               ret = PTR_ERR(vma);
+               goto out;
+       }
 
-       mm->context.vdso = (void *)addr;
+       mm->context.vdso = (void *)vdso_addr;
+       ret = 0;
 
-up_fail:
+out:
        up_write(&mm->mmap_sem);
        return ret;
 }
-
-const char *arch_vma_name(struct vm_area_struct *vma)
-{
-       if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
-               return "[vdso]";
-       return NULL;
-}
index 07d32a4aea60e418892ffb27cbae05c11099a92f..0a93e83cd01479a4abc952e2e41a853dbf4159b9 100644 (file)
@@ -17,7 +17,9 @@ OUTPUT_ARCH(mips)
 ENTRY(kernel_entry)
 PHDRS {
        text PT_LOAD FLAGS(7);  /* RWX */
+#ifndef CONFIG_CAVIUM_OCTEON_SOC
        note PT_NOTE FLAGS(4);  /* R__ */
+#endif /* CAVIUM_OCTEON_SOC */
 }
 
 #ifdef CONFIG_32BIT
@@ -71,7 +73,12 @@ SECTIONS
                __stop___dbe_table = .;
        }
 
-       NOTES :text :note
+#ifdef CONFIG_CAVIUM_OCTEON_SOC
+#define NOTES_HEADER
+#else /* CONFIG_CAVIUM_OCTEON_SOC */
+#define NOTES_HEADER :note
+#endif /* CONFIG_CAVIUM_OCTEON_SOC */
+       NOTES :text NOTES_HEADER
        .dummy : { *(.dummy) } :text
 
        _sdata = .;                     /* Start of data section */
@@ -132,6 +139,11 @@ SECTIONS
        __appended_dtb = .;
        /* leave space for appended DTB */
        . += 0x100000;
+#elif defined(CONFIG_MIPS_ELF_APPENDED_DTB)
+       .appended_dtb : AT(ADDR(.appended_dtb) - LOAD_OFFSET) {
+               *(.appended_dtb)
+               KEEP(*(.appended_dtb))
+       }
 #endif
        /*
         * Align to 64K in attempt to eliminate holes before the
@@ -181,6 +193,7 @@ SECTIONS
        DISCARDS
        /DISCARD/ : {
                /* ABI crap starts here */
+               *(.MIPS.abiflags)
                *(.MIPS.options)
                *(.options)
                *(.pdr)
index d5fa3eaf39a106546f52d82ec3e5391302ef8dec..41b1b090f56f6b73afc50240318634a4988ef427 100644 (file)
@@ -1581,7 +1581,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
 
        base = (inst >> 21) & 0x1f;
        op_inst = (inst >> 16) & 0x1f;
-       offset = inst & 0xffff;
+       offset = (int16_t)inst;
        cache = (inst >> 16) & 0x3;
        op = (inst >> 18) & 0x7;
 
index c567240386a0f10818b0e06433f4b33b1bf5e6dc..7e2210846b8b9d1519f679e6a0950fcaf1e6dfd5 100644 (file)
 #define PT_HOST_USERLOCAL   PT_EPC
 
 #define CP0_DDATA_LO        $28,3
-#define CP0_CONFIG3         $16,3
-#define CP0_CONFIG5         $16,5
-#define CP0_EBASE           $15,1
-
-#define CP0_INTCTL          $12,1
-#define CP0_SRSCTL          $12,2
-#define CP0_SRSMAP          $12,3
-#define CP0_HWRENA          $7,0
 
 /* Resume Flags */
 #define RESUME_FLAG_HOST        (1<<1)  /* Resume host? */
@@ -165,9 +157,11 @@ FEXPORT(__kvm_mips_vcpu_run)
 
 FEXPORT(__kvm_mips_load_asid)
        /* Set the ASID for the Guest Kernel */
-       INT_SLL t0, t0, 1       /* with kseg0 @ 0x40000000, kernel */
-                               /* addresses shift to 0x80000000 */
-       bltz    t0, 1f          /* If kernel */
+       PTR_L   t0, VCPU_COP0(k1)
+       LONG_L  t0, COP0_STATUS(t0)
+       andi    t0, KSU_USER | ST0_ERL | ST0_EXL
+       xori    t0, KSU_USER
+       bnez    t0, 1f          /* If kernel */
         INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
        INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
 1:
@@ -482,9 +476,11 @@ __kvm_mips_return_to_guest:
        mtc0    t0, CP0_EPC
 
        /* Set the ASID for the Guest Kernel */
-       INT_SLL t0, t0, 1       /* with kseg0 @ 0x40000000, kernel */
-                               /* addresses shift to 0x80000000 */
-       bltz    t0, 1f          /* If kernel */
+       PTR_L   t0, VCPU_COP0(k1)
+       LONG_L  t0, COP0_STATUS(t0)
+       andi    t0, KSU_USER | ST0_ERL | ST0_EXL
+       xori    t0, KSU_USER
+       bnez    t0, 1f          /* If kernel */
         INT_ADDIU t1, k1, VCPU_GUEST_KERNEL_ASID  /* (BD)  */
        INT_ADDIU t1, k1, VCPU_GUEST_USER_ASID    /* else user */
 1:
index 49ff3bfc007e534529d0f61d21b6fddd6578d145..b9b803facdbf7594dc700ca828a2ced604e617aa 100644 (file)
@@ -279,7 +279,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 
        if (!gebase) {
                err = -ENOMEM;
-               goto out_free_cpu;
+               goto out_uninit_cpu;
        }
        kvm_debug("Allocated %d bytes for KVM Exception Handlers @ %p\n",
                  ALIGN(size, PAGE_SIZE), gebase);
@@ -343,6 +343,9 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 out_free_gebase:
        kfree(gebase);
 
+out_uninit_cpu:
+       kvm_vcpu_uninit(vcpu);
+
 out_free_cpu:
        kfree(vcpu);
 
index 3fc2e6d70c7798f98c6b65b26e8a4f3e024584b2..a0706fd4ce0a0f0b3e9a531b31692fd6e1c0342f 100644 (file)
@@ -99,6 +99,23 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 }
 EXPORT_SYMBOL(clk_set_rate);
 
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (unlikely(!clk_good(clk)))
+               return 0;
+       if (clk->rates && *clk->rates) {
+               unsigned long *r = clk->rates;
+
+               while (*r && (*r != rate))
+                       r++;
+               if (!*r) {
+                       return clk->rate;
+               }
+       }
+       return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
 int clk_enable(struct clk *clk)
 {
        if (unlikely(!clk_good(clk)))
index 77e4bdb1fe8cae2145b0d9875f1d8b69e3fe5d10..7376ce817eda6c6d23a20f1d1c853c24ccd5eb27 100644 (file)
 #define CLOCK_240M     240000000
 #define CLOCK_250M     250000000
 #define CLOCK_266M     266666666
+#define CLOCK_288M     288888888
 #define CLOCK_300M     300000000
 #define CLOCK_333M     333333333
+#define CLOCK_360M     360000000
 #define CLOCK_393M     393215332
 #define CLOCK_400M     400000000
+#define CLOCK_432M     432000000
 #define CLOCK_450M     450000000
 #define CLOCK_500M     500000000
 #define CLOCK_600M     600000000
+#define CLOCK_666M     666666666
+#define CLOCK_720M     720000000
 
 /* clock out speeds */
 #define CLOCK_32_768K  32768
@@ -80,4 +85,12 @@ extern unsigned long ltq_vr9_cpu_hz(void);
 extern unsigned long ltq_vr9_fpi_hz(void);
 extern unsigned long ltq_vr9_pp32_hz(void);
 
+extern unsigned long ltq_ar10_cpu_hz(void);
+extern unsigned long ltq_ar10_fpi_hz(void);
+extern unsigned long ltq_ar10_pp32_hz(void);
+
+extern unsigned long ltq_grx390_cpu_hz(void);
+extern unsigned long ltq_grx390_fpi_hz(void);
+extern unsigned long ltq_grx390_pp32_hz(void);
+
 #endif
index 2c218c3bbca57be3d029cdb3320b712092bccd46..2e7f60c9fc5dfc9a56f3d5db2aed46fcbffc6002 100644 (file)
@@ -369,8 +369,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                if (of_address_to_resource(node, i, &res))
                        panic("Failed to get icu memory range");
 
-               if (request_mem_region(res.start, resource_size(&res),
-                                       res.name) < 0)
+               if (!request_mem_region(res.start, resource_size(&res),
+                                       res.name))
                        pr_err("Failed to request icu memory");
 
                ltq_icu_membase[i] = ioremap_nocache(res.start,
@@ -449,8 +449,8 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                if (ret != exin_avail)
                        panic("failed to load external irq resources");
 
-               if (request_mem_region(res.start, resource_size(&res),
-                                                       res.name) < 0)
+               if (!request_mem_region(res.start, resource_size(&res),
+                                                       res.name))
                        pr_err("Failed to request eiu memory");
 
                ltq_eiu_membase = ioremap_nocache(res.start,
index 0db099ecc01648cca11a69cddcaab31c8c0a099e..297bcaa6b5d32b346c25fc9414a1e4690094c092 100644 (file)
@@ -77,8 +77,6 @@ void __init plat_mem_setup(void)
         * parsed resulting in our memory appearing
         */
        __dt_setup_arch(__dtb_start);
-
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 }
 
 void __init device_tree_init(void)
index 8750dc0a1bf678c5bd8500260816d6070b949aca..07f6d5b0b65ee10ccca231e0abab24d08462332e 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/io.h>
@@ -25,9 +26,9 @@ static unsigned int ram_clocks[] = {
 /* legacy xway clock */
 #define CGU_SYS                        0x10
 
-/* vr9 clock */
-#define CGU_SYS_VR9            0x0c
-#define CGU_IF_CLK_VR9         0x24
+/* vr9, ar10/grx390 clock */
+#define CGU_SYS_XRX            0x0c
+#define CGU_IF_CLK_AR10                0x24
 
 unsigned long ltq_danube_fpi_hz(void)
 {
@@ -87,8 +88,9 @@ unsigned long ltq_ar9_fpi_hz(void)
        unsigned long sys = ltq_ar9_sys_hz();
 
        if (ltq_cgu_r32(CGU_SYS) & BIT(0))
-               return sys;
-       return sys >> 1;
+               return sys / 3;
+       else
+               return sys / 2;
 }
 
 unsigned long ltq_ar9_cpu_hz(void)
@@ -104,7 +106,7 @@ unsigned long ltq_vr9_cpu_hz(void)
        unsigned int cpu_sel;
        unsigned long clk;
 
-       cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf;
+       cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf;
 
        switch (cpu_sel) {
        case 0:
@@ -145,7 +147,7 @@ unsigned long ltq_vr9_fpi_hz(void)
        unsigned long clk;
 
        cpu_clk = ltq_vr9_cpu_hz();
-       ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3;
+       ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3;
 
        switch (ocp_sel) {
        case 0:
@@ -174,15 +176,18 @@ unsigned long ltq_vr9_fpi_hz(void)
 
 unsigned long ltq_vr9_pp32_hz(void)
 {
-       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3;
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
        unsigned long clk;
 
        switch (clksys) {
+       case 0:
+               clk = CLOCK_500M;
+               break;
        case 1:
-               clk = CLOCK_450M;
+               clk = CLOCK_432M;
                break;
        case 2:
-               clk = CLOCK_300M;
+               clk = CLOCK_288M;
                break;
        default:
                clk = CLOCK_500M;
@@ -191,3 +196,158 @@ unsigned long ltq_vr9_pp32_hz(void)
 
        return clk;
 }
+
+unsigned long ltq_ar10_cpu_hz(void)
+{
+       unsigned int clksys;
+       int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1;
+       int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7;
+
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_500M;
+               break;
+       case 1:
+               clksys = CLOCK_600M;
+               break;
+       default:
+               clksys = CLOCK_500M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 0:
+               return clksys;
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys;
+       }
+}
+
+unsigned long ltq_ar10_fpi_hz(void)
+{
+       int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf;
+
+       switch (freq_fpi) {
+       case 1:
+               return CLOCK_300M;
+       case 5:
+               return CLOCK_250M;
+       case 2:
+               return CLOCK_150M;
+       case 6:
+               return CLOCK_125M;
+
+       default:
+               return CLOCK_125M;
+       }
+}
+
+unsigned long ltq_ar10_pp32_hz(void)
+{
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+       unsigned long clk;
+
+       switch (clksys) {
+       case 1:
+               clk = CLOCK_250M;
+               break;
+       case 4:
+               clk = CLOCK_400M;
+               break;
+       default:
+               clk = CLOCK_250M;
+               break;
+       }
+
+       return clk;
+}
+
+unsigned long ltq_grx390_cpu_hz(void)
+{
+       unsigned int clksys;
+       int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+       int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7);
+
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_600M;
+               break;
+       case 1:
+               clksys = CLOCK_666M;
+               break;
+       case 2:
+               clksys = CLOCK_720M;
+               break;
+       default:
+               clksys = CLOCK_600M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 0:
+               return clksys;
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys;
+       }
+}
+
+unsigned long ltq_grx390_fpi_hz(void)
+{
+       /* fpi clock is derived from ddr_clk */
+       unsigned int clksys;
+       int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
+       int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7);
+       switch (cpu_fs) {
+       case 0:
+               clksys = CLOCK_600M;
+               break;
+       case 1:
+               clksys = CLOCK_666M;
+               break;
+       case 2:
+               clksys = CLOCK_720M;
+               break;
+       default:
+               clksys = CLOCK_600M;
+               break;
+       }
+
+       switch (freq_div) {
+       case 1:
+               return clksys >> 1;
+       case 2:
+               return clksys >> 2;
+       default:
+               return clksys >> 1;
+       }
+}
+
+unsigned long ltq_grx390_pp32_hz(void)
+{
+       unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
+       unsigned long clk;
+
+       switch (clksys) {
+       case 1:
+               clk = CLOCK_250M;
+               break;
+       case 2:
+               clk = CLOCK_432M;
+               break;
+       case 4:
+               clk = CLOCK_400M;
+               break;
+       default:
+               clk = CLOCK_250M;
+               break;
+       }
+       return clk;
+}
index 248429ab2622bb7e404c204e08551ef57787ffaa..8f6e02f1e9650b99830a14bd160ddf12856a9ee1 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/export.h>
 #define SOC_TWINPASS   "Twinpass"
 #define SOC_AMAZON_SE  "Amazon_SE"
 #define SOC_AR9                "AR9"
-#define SOC_GR9                "GR9"
-#define SOC_VR9                "VR9"
+#define SOC_GR9                "GRX200"
+#define SOC_VR9                "xRX200"
+#define SOC_VRX220     "xRX220"
+#define SOC_AR10       "xRX300"
+#define SOC_GRX390     "xRX330"
 
 #define COMP_DANUBE    "lantiq,danube"
 #define COMP_TWINPASS  "lantiq,twinpass"
@@ -28,6 +32,8 @@
 #define COMP_AR9       "lantiq,ar9"
 #define COMP_GR9       "lantiq,gr9"
 #define COMP_VR9       "lantiq,vr9"
+#define COMP_AR10      "lantiq,ar10"
+#define COMP_GRX390    "lantiq,grx390"
 
 #define PART_SHIFT     12
 #define PART_MASK      0x0FFFFFFF
@@ -101,6 +107,12 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
                i->compatible = COMP_VR9;
                break;
 
+       case SOC_ID_VRX220:
+               i->name = SOC_VRX220;
+               i->type = SOC_TYPE_VRX220;
+               i->compatible = COMP_VR9;
+               break;
+
        case SOC_ID_GRX282_2:
        case SOC_ID_GRX288_2:
                i->name = SOC_GR9;
@@ -108,6 +120,25 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
                i->compatible = COMP_GR9;
                break;
 
+       case SOC_ID_ARX362:
+       case SOC_ID_ARX368:
+       case SOC_ID_ARX382:
+       case SOC_ID_ARX388:
+       case SOC_ID_URX388:
+               i->name = SOC_AR10;
+               i->type = SOC_TYPE_AR10;
+               i->compatible = COMP_AR10;
+               break;
+
+       case SOC_ID_GRX383:
+       case SOC_ID_GRX369:
+       case SOC_ID_GRX387:
+       case SOC_ID_GRX389:
+               i->name = SOC_GRX390;
+               i->type = SOC_TYPE_GRX390;
+               i->compatible = COMP_GRX390;
+               break;
+
        default:
                unreachable();
                break;
index fe68f9ae47c1487afde62c2bddcf1d5a94ff758a..bc29bb349e94e227fc0b015544d588eddafe5a57 100644 (file)
@@ -4,6 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/init.h>
@@ -22,9 +23,6 @@
 
 #include "../prom.h"
 
-#define ltq_rcu_w32(x, y)      ltq_w32((x), ltq_rcu_membase + (y))
-#define ltq_rcu_r32(x)         ltq_r32(ltq_rcu_membase + (x))
-
 /* reset request register */
 #define RCU_RST_REQ            0x0010
 /* reset status register */
 /* vr9 gphy registers */
 #define RCU_GFS_ADD0_XRX200    0x0020
 #define RCU_GFS_ADD1_XRX200    0x0068
+/* xRX300 gphy registers */
+#define RCU_GFS_ADD0_XRX300    0x0020
+#define RCU_GFS_ADD1_XRX300    0x0058
+#define RCU_GFS_ADD2_XRX300    0x00AC
+/* xRX330 gphy registers */
+#define RCU_GFS_ADD0_XRX330    0x0020
+#define RCU_GFS_ADD1_XRX330    0x0058
+#define RCU_GFS_ADD2_XRX330    0x00AC
+#define RCU_GFS_ADD3_XRX330    0x0264
+
+/* xbar BE flag */
+#define RCU_AHB_ENDIAN          0x004C
+#define RCU_VR9_BE_AHB1S        0x00000008
 
 /* reboot bit */
 #define RCU_RD_GPHY0_XRX200    BIT(31)
 #define RCU_RD_SRST            BIT(30)
 #define RCU_RD_GPHY1_XRX200    BIT(29)
+/* xRX300 bits */
+#define RCU_RD_GPHY0_XRX300    BIT(31)
+#define RCU_RD_GPHY1_XRX300    BIT(29)
+#define RCU_RD_GPHY2_XRX300    BIT(28)
+/* xRX330 bits */
+#define RCU_RD_GPHY0_XRX330    BIT(31)
+#define RCU_RD_GPHY1_XRX330    BIT(29)
+#define RCU_RD_GPHY2_XRX330    BIT(28)
+#define RCU_RD_GPHY3_XRX330    BIT(10)
 
 /* reset cause */
 #define RCU_STAT_SHIFT         26
 #define RCU_BOOT_SEL(x)                ((x >> 18) & 0x7)
 #define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
 
+/* dwc2 USB configuration registers */
+#define RCU_USB1CFG            0x0018
+#define RCU_USB2CFG            0x0034
+
+/* USB DMA endianness bits */
+#define RCU_USBCFG_HDSEL_BIT   BIT(11)
+#define RCU_USBCFG_HOST_END_BIT        BIT(10)
+#define RCU_USBCFG_SLV_END_BIT BIT(9)
+
+/* USB reset bits */
+#define RCU_USBRESET           0x0010
+
+#define USBRESET_BIT           BIT(4)
+
+#define RCU_USBRESET2          0x0048
+
+#define USB1RESET_BIT          BIT(4)
+#define USB2RESET_BIT          BIT(5)
+
+#define RCU_CFG1A              0x0038
+#define RCU_CFG1B              0x003C
+
+/* USB PMU devices */
+#define PMU_AHBM               BIT(15)
+#define PMU_USB0               BIT(6)
+#define PMU_USB1               BIT(27)
+
+/* USB PHY PMU devices */
+#define PMU_USB0_P             BIT(0)
+#define PMU_USB1_P             BIT(26)
+
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
 static struct device_node *ltq_rcu_np;
+static DEFINE_SPINLOCK(ltq_rcu_lock);
+
+static void ltq_rcu_w32(uint32_t val, uint32_t reg_off)
+{
+       ltq_w32(val, ltq_rcu_membase + reg_off);
+}
+
+static uint32_t ltq_rcu_r32(uint32_t reg_off)
+{
+       return ltq_r32(ltq_rcu_membase + reg_off);
+}
+
+static void ltq_rcu_w32_mask(uint32_t clr, uint32_t set, uint32_t reg_off)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ltq_rcu_lock, flags);
+       ltq_rcu_w32((ltq_rcu_r32(reg_off) & ~(clr)) | (set), reg_off);
+       spin_unlock_irqrestore(&ltq_rcu_lock, flags);
+}
 
 /* This function is used by the watchdog driver */
 int ltq_reset_cause(void)
@@ -67,15 +138,40 @@ unsigned char ltq_boot_select(void)
        return RCU_BOOT_SEL(val);
 }
 
-/* reset / boot a gphy */
-static struct ltq_xrx200_gphy_reset {
+struct ltq_gphy_reset {
        u32 rd;
        u32 addr;
-} xrx200_gphy[] = {
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx200_gphy[] = {
        {RCU_RD_GPHY0_XRX200, RCU_GFS_ADD0_XRX200},
        {RCU_RD_GPHY1_XRX200, RCU_GFS_ADD1_XRX200},
 };
 
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx300_gphy[] = {
+       {RCU_RD_GPHY0_XRX300, RCU_GFS_ADD0_XRX300},
+       {RCU_RD_GPHY1_XRX300, RCU_GFS_ADD1_XRX300},
+       {RCU_RD_GPHY2_XRX300, RCU_GFS_ADD2_XRX300},
+};
+
+/* reset / boot a gphy */
+static struct ltq_gphy_reset xrx330_gphy[] = {
+       {RCU_RD_GPHY0_XRX330, RCU_GFS_ADD0_XRX330},
+       {RCU_RD_GPHY1_XRX330, RCU_GFS_ADD1_XRX330},
+       {RCU_RD_GPHY2_XRX330, RCU_GFS_ADD2_XRX330},
+       {RCU_RD_GPHY3_XRX330, RCU_GFS_ADD3_XRX330},
+};
+
+static void xrx200_gphy_boot_addr(struct ltq_gphy_reset *phy_regs,
+                                 dma_addr_t dev_addr)
+{
+       ltq_rcu_w32_mask(0, phy_regs->rd, RCU_RST_REQ);
+       ltq_rcu_w32(dev_addr, phy_regs->addr);
+       ltq_rcu_w32_mask(phy_regs->rd, 0,  RCU_RST_REQ);
+}
+
 /* reset and boot a gphy. these phys only exist on xrx200 SoC */
 int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
 {
@@ -86,23 +182,34 @@ int xrx200_gphy_boot(struct device *dev, unsigned int id, dma_addr_t dev_addr)
                return -EINVAL;
        }
 
-       clk = clk_get_sys("1f203000.rcu", "gphy");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-
-       clk_enable(clk);
-
-       if (id > 1) {
-               dev_err(dev, "%u is an invalid gphy id\n", id);
-               return -EINVAL;
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               clk = clk_get_sys("1f203000.rcu", "gphy");
+               if (IS_ERR(clk))
+                       return PTR_ERR(clk);
+               clk_enable(clk);
        }
+
        dev_info(dev, "booting GPHY%u firmware at %X\n", id, dev_addr);
 
-       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | xrx200_gphy[id].rd,
-                       RCU_RST_REQ);
-       ltq_rcu_w32(dev_addr, xrx200_gphy[id].addr);
-       ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~xrx200_gphy[id].rd,
-                       RCU_RST_REQ);
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               if (id >= ARRAY_SIZE(xrx200_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx200_gphy[id], dev_addr);
+       } else if (of_machine_is_compatible("lantiq,ar10")) {
+               if (id >= ARRAY_SIZE(xrx300_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx300_gphy[id], dev_addr);
+       } else if (of_machine_is_compatible("lantiq,grx390")) {
+               if (id >= ARRAY_SIZE(xrx330_gphy)) {
+                       dev_err(dev, "%u is an invalid gphy id\n", id);
+                       return -EINVAL;
+               }
+               xrx200_gphy_boot_addr(&xrx330_gphy[id], dev_addr);
+       }
        return 0;
 }
 
@@ -200,6 +307,45 @@ static void ltq_machine_power_off(void)
        unreachable();
 }
 
+static void ltq_usb_init(void)
+{
+       /* Power for USB cores 1 & 2 */
+       ltq_pmu_enable(PMU_AHBM);
+       ltq_pmu_enable(PMU_USB0);
+       ltq_pmu_enable(PMU_USB1);
+
+       ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B);
+
+       /* Enable USB PHY power for cores 1 & 2 */
+       ltq_pmu_enable(PMU_USB0_P);
+       ltq_pmu_enable(PMU_USB1_P);
+
+       /* Configure cores to host mode */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT,
+               RCU_USB1CFG);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT,
+               RCU_USB2CFG);
+
+       /* Select DMA endianness (Host-endian: big-endian) */
+       ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT)
+               | RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG);
+       ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT)
+               | RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG);
+
+       /* Hard reset USB state machines */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET);
+       udelay(50 * 1000);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET);
+
+       /* Soft reset USB state machines */
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+               | USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2);
+       udelay(50 * 1000);
+       ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+               & ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2);
+}
+
 static int __init mips_reboot_setup(void)
 {
        struct resource res;
@@ -216,13 +362,21 @@ static int __init mips_reboot_setup(void)
        if (of_address_to_resource(ltq_rcu_np, 0, &res))
                panic("Failed to get rcu memory range");
 
-       if (request_mem_region(res.start, resource_size(&res), res.name) < 0)
+       if (!request_mem_region(res.start, resource_size(&res), res.name))
                pr_err("Failed to request rcu memory");
 
        ltq_rcu_membase = ioremap_nocache(res.start, resource_size(&res));
        if (!ltq_rcu_membase)
                panic("Failed to remap core memory");
 
+       if (of_machine_is_compatible("lantiq,ar9") ||
+           of_machine_is_compatible("lantiq,vr9"))
+               ltq_usb_init();
+
+       if (of_machine_is_compatible("lantiq,vr9"))
+               ltq_rcu_w32(ltq_rcu_r32(RCU_AHB_ENDIAN) | RCU_VR9_BE_AHB1S,
+                           RCU_AHB_ENDIAN);
+
        _machine_restart = ltq_machine_restart;
        _machine_halt = ltq_machine_halt;
        pm_power_off = ltq_machine_power_off;
index 2b15491de49462e27e71df6758a49efbd4b29ef4..80554e8f603758f78352b8eb3a8fa4d20df9af7f 100644 (file)
@@ -4,11 +4,13 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
 #include <linux/ioport.h>
 #include <linux/export.h>
 #include <linux/clkdev.h>
+#include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include "../clk.h"
 #include "../prom.h"
 
-/* clock control register */
+/* clock control register for legacy */
 #define CGU_IFCCR      0x0018
 #define CGU_IFCCR_VR9  0x0024
-/* system clock register */
+/* system clock register for legacy */
 #define CGU_SYS                0x0010
 /* pci control register */
 #define CGU_PCICR      0x0034
 #define CGU_PCICR_VR9  0x0038
 /* ephy configuration register */
 #define CGU_EPHY       0x10
+
+/* Legacy PMU register for ar9, ase, danube */
 /* power control register */
 #define PMU_PWDCR      0x1C
 /* power status register */
 /* power status register */
 #define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
 
+
+/* PMU register for ar10 and grx390 */
+
+/* First register set */
+#define PMU_CLK_SR     0x20 /* status */
+#define PMU_CLK_CR_A   0x24 /* Enable */
+#define PMU_CLK_CR_B   0x28 /* Disable */
+/* Second register set */
+#define PMU_CLK_SR1    0x30 /* status */
+#define PMU_CLK_CR1_A  0x34 /* Enable */
+#define PMU_CLK_CR1_B  0x38 /* Disable */
+/* Third register set */
+#define PMU_ANA_SR     0x40 /* status */
+#define PMU_ANA_CR_A   0x44 /* Enable */
+#define PMU_ANA_CR_B   0x48 /* Disable */
+
+/* Status */
+static u32 pmu_clk_sr[] = {
+       PMU_CLK_SR,
+       PMU_CLK_SR1,
+       PMU_ANA_SR,
+};
+
+/* Enable */
+static u32 pmu_clk_cr_a[] = {
+       PMU_CLK_CR_A,
+       PMU_CLK_CR1_A,
+       PMU_ANA_CR_A,
+};
+
+/* Disable */
+static u32 pmu_clk_cr_b[] = {
+       PMU_CLK_CR_B,
+       PMU_CLK_CR1_B,
+       PMU_ANA_CR_B,
+};
+
+#define PWDCR_EN_XRX(x)                (pmu_clk_cr_a[(x)])
+#define PWDCR_DIS_XRX(x)       (pmu_clk_cr_b[(x)])
+#define PWDSR_XRX(x)           (pmu_clk_sr[(x)])
+
 /* clock gates that we can en/disable */
 #define PMU_USB0_P     BIT(0)
+#define PMU_ASE_SDIO   BIT(2) /* ASE special */
 #define PMU_PCI                BIT(4)
 #define PMU_DMA                BIT(5)
 #define PMU_USB0       BIT(6)
 #define PMU_ASC0       BIT(7)
 #define PMU_EPHY       BIT(7)  /* ase */
+#define PMU_USIF       BIT(7) /* from vr9 until grx390 */
 #define PMU_SPI                BIT(8)
 #define PMU_DFE                BIT(9)
 #define PMU_EBU                BIT(10)
 #define PMU_AHBS       BIT(13) /* vr9 */
 #define PMU_FPI                BIT(14)
 #define PMU_AHBM       BIT(15)
+#define PMU_SDIO       BIT(16) /* danube, ar9, vr9 */
 #define PMU_ASC1       BIT(17)
 #define PMU_PPE_QSB    BIT(18)
 #define PMU_PPE_SLL01  BIT(19)
+#define PMU_DEU                BIT(20)
 #define PMU_PPE_TC     BIT(21)
 #define PMU_PPE_EMA    BIT(22)
 #define PMU_PPE_DPLUM  BIT(23)
+#define PMU_PPE_DP     BIT(23)
 #define PMU_PPE_DPLUS  BIT(24)
 #define PMU_USB1_P     BIT(26)
 #define PMU_USB1       BIT(27)
 #define PMU_GPHY       BIT(30)
 #define PMU_PCIE_CLK   BIT(31)
 
-#define PMU1_PCIE_PHY  BIT(0)
+#define PMU1_PCIE_PHY  BIT(0)  /* vr9-specific,moved in ar10/grx390 */
 #define PMU1_PCIE_CTL  BIT(1)
 #define PMU1_PCIE_PDI  BIT(4)
 #define PMU1_PCIE_MSI  BIT(5)
+#define PMU1_CKE       BIT(6)
+#define PMU1_PCIE1_CTL BIT(17)
+#define PMU1_PCIE1_PDI BIT(20)
+#define PMU1_PCIE1_MSI BIT(21)
+#define PMU1_PCIE2_CTL BIT(25)
+#define PMU1_PCIE2_PDI BIT(26)
+#define PMU1_PCIE2_MSI BIT(27)
+
+#define PMU_ANALOG_USB0_P      BIT(0)
+#define PMU_ANALOG_USB1_P      BIT(1)
+#define PMU_ANALOG_PCIE0_P     BIT(8)
+#define PMU_ANALOG_PCIE1_P     BIT(9)
+#define PMU_ANALOG_PCIE2_P     BIT(10)
+#define PMU_ANALOG_DSL_AFE     BIT(16)
+#define PMU_ANALOG_DCDC_2V5    BIT(17)
+#define PMU_ANALOG_DCDC_1VX    BIT(18)
+#define PMU_ANALOG_DCDC_1V0    BIT(19)
 
 #define pmu_w32(x, y)  ltq_w32((x), pmu_membase + (y))
 #define pmu_r32(x)     ltq_r32(pmu_membase + (x))
 
+#define XBAR_ALWAYS_LAST       0x430
+#define XBAR_FPI_BURST_EN      BIT(1)
+#define XBAR_AHB_BURST_EN      BIT(2)
+
+#define xbar_w32(x, y) ltq_w32((x), ltq_xbar_membase + (y))
+#define xbar_r32(x)    ltq_r32(ltq_xbar_membase + (x))
+
 static void __iomem *pmu_membase;
+static void __iomem *ltq_xbar_membase;
 void __iomem *ltq_cgu_membase;
 void __iomem *ltq_ebu_membase;
 
 static u32 ifccr = CGU_IFCCR;
 static u32 pcicr = CGU_PCICR;
 
+static DEFINE_SPINLOCK(g_pmu_lock);
+
 /* legacy function kept alive to ease clkdev transition */
 void ltq_pmu_enable(unsigned int module)
 {
-       int err = 1000000;
+       int retry = 1000000;
 
+       spin_lock(&g_pmu_lock);
        pmu_w32(pmu_r32(PMU_PWDCR) & ~module, PMU_PWDCR);
-       do {} while (--err && (pmu_r32(PMU_PWDSR) & module));
+       do {} while (--retry && (pmu_r32(PMU_PWDSR) & module));
+       spin_unlock(&g_pmu_lock);
 
-       if (!err)
+       if (!retry)
                panic("activating PMU module failed!");
 }
 EXPORT_SYMBOL(ltq_pmu_enable);
@@ -101,7 +180,15 @@ EXPORT_SYMBOL(ltq_pmu_enable);
 /* legacy function kept alive to ease clkdev transition */
 void ltq_pmu_disable(unsigned int module)
 {
+       int retry = 1000000;
+
+       spin_lock(&g_pmu_lock);
        pmu_w32(pmu_r32(PMU_PWDCR) | module, PMU_PWDCR);
+       do {} while (--retry && (!(pmu_r32(PMU_PWDSR) & module)));
+       spin_unlock(&g_pmu_lock);
+
+       if (!retry)
+               pr_warn("deactivating PMU module failed!");
 }
 EXPORT_SYMBOL(ltq_pmu_disable);
 
@@ -123,9 +210,20 @@ static int pmu_enable(struct clk *clk)
 {
        int retry = 1000000;
 
-       pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
-               PWDCR(clk->module));
-       do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
+       if (of_machine_is_compatible("lantiq,ar10")
+           || of_machine_is_compatible("lantiq,grx390")) {
+               pmu_w32(clk->bits, PWDCR_EN_XRX(clk->module));
+               do {} while (--retry &&
+                            (!(pmu_r32(PWDSR_XRX(clk->module)) & clk->bits)));
+
+       } else {
+               spin_lock(&g_pmu_lock);
+               pmu_w32(pmu_r32(PWDCR(clk->module)) & ~clk->bits,
+                               PWDCR(clk->module));
+               do {} while (--retry &&
+                            (pmu_r32(PWDSR(clk->module)) & clk->bits));
+               spin_unlock(&g_pmu_lock);
+       }
 
        if (!retry)
                panic("activating PMU module failed!");
@@ -136,8 +234,24 @@ static int pmu_enable(struct clk *clk)
 /* disable a clock gate */
 static void pmu_disable(struct clk *clk)
 {
-       pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
-               PWDCR(clk->module));
+       int retry = 1000000;
+
+       if (of_machine_is_compatible("lantiq,ar10")
+           || of_machine_is_compatible("lantiq,grx390")) {
+               pmu_w32(clk->bits, PWDCR_DIS_XRX(clk->module));
+               do {} while (--retry &&
+                            (pmu_r32(PWDSR_XRX(clk->module)) & clk->bits));
+       } else {
+               spin_lock(&g_pmu_lock);
+               pmu_w32(pmu_r32(PWDCR(clk->module)) | clk->bits,
+                               PWDCR(clk->module));
+               do {} while (--retry &&
+                            (!(pmu_r32(PWDSR(clk->module)) & clk->bits)));
+               spin_unlock(&g_pmu_lock);
+       }
+
+       if (!retry)
+               pr_warn("deactivating PMU module failed!");
 }
 
 /* the pci enable helper */
@@ -179,6 +293,16 @@ static void pci_ext_disable(struct clk *clk)
        ltq_cgu_w32((1 << 31) | (1 << 30), pcicr);
 }
 
+static void xbar_fpi_burst_disable(void)
+{
+       u32 reg;
+
+       /* bit 1 as 1 --burst; bit 1 as 0 -- single */
+       reg = xbar_r32(XBAR_ALWAYS_LAST);
+       reg &= ~XBAR_FPI_BURST_EN;
+       xbar_w32(reg, XBAR_ALWAYS_LAST);
+}
+
 /* enable a clockout source */
 static int clkout_enable(struct clk *clk)
 {
@@ -202,8 +326,8 @@ static int clkout_enable(struct clk *clk)
 }
 
 /* manage the clock gates via PMU */
-static void clkdev_add_pmu(const char *dev, const char *con,
-                                       unsigned int module, unsigned int bits)
+static void clkdev_add_pmu(const char *dev, const char *con, bool deactivate,
+                          unsigned int module, unsigned int bits)
 {
        struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
@@ -214,6 +338,13 @@ static void clkdev_add_pmu(const char *dev, const char *con,
        clk->disable = pmu_disable;
        clk->module = module;
        clk->bits = bits;
+       if (deactivate) {
+               /*
+                * Disable it during the initialization. Module should enable
+                * when used
+                */
+               pmu_disable(clk);
+       }
        clkdev_add(&clk->cl);
 }
 
@@ -312,12 +443,12 @@ void __init ltq_soc_init(void)
                        of_address_to_resource(np_ebu, 0, &res_ebu))
                panic("Failed to get core resources");
 
-       if ((request_mem_region(res_pmu.start, resource_size(&res_pmu),
-                               res_pmu.name) < 0) ||
-               (request_mem_region(res_cgu.start, resource_size(&res_cgu),
-                               res_cgu.name) < 0) ||
-               (request_mem_region(res_ebu.start, resource_size(&res_ebu),
-                               res_ebu.name) < 0))
+       if (!request_mem_region(res_pmu.start, resource_size(&res_pmu),
+                               res_pmu.name) ||
+               !request_mem_region(res_cgu.start, resource_size(&res_cgu),
+                               res_cgu.name) ||
+               !request_mem_region(res_ebu.start, resource_size(&res_ebu),
+                               res_ebu.name))
                pr_err("Failed to request core resources");
 
        pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
@@ -328,17 +459,37 @@ void __init ltq_soc_init(void)
        if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
                panic("Failed to remap core resources");
 
+       if (of_machine_is_compatible("lantiq,vr9")) {
+               struct resource res_xbar;
+               struct device_node *np_xbar =
+                               of_find_compatible_node(NULL, NULL,
+                                                       "lantiq,xbar-xway");
+
+               if (!np_xbar)
+                       panic("Failed to load xbar nodes from devicetree");
+               if (of_address_to_resource(np_pmu, 0, &res_xbar))
+                       panic("Failed to get xbar resources");
+               if (request_mem_region(res_xbar.start, resource_size(&res_xbar),
+                       res_xbar.name) < 0)
+                       panic("Failed to get xbar resources");
+
+               ltq_xbar_membase = ioremap_nocache(res_xbar.start,
+                                                  resource_size(&res_xbar));
+               if (!ltq_xbar_membase)
+                       panic("Failed to remap xbar resources");
+       }
+
        /* make sure to unprotect the memory region where flash is located */
        ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
 
        /* add our generic xway clocks */
-       clkdev_add_pmu("10000000.fpi", NULL, 0, PMU_FPI);
-       clkdev_add_pmu("1e100400.serial", NULL, 0, PMU_ASC0);
-       clkdev_add_pmu("1e100a00.gptu", NULL, 0, PMU_GPT);
-       clkdev_add_pmu("1e100bb0.stp", NULL, 0, PMU_STP);
-       clkdev_add_pmu("1e104100.dma", NULL, 0, PMU_DMA);
-       clkdev_add_pmu("1e100800.spi", NULL, 0, PMU_SPI);
-       clkdev_add_pmu("1e105300.ebu", NULL, 0, PMU_EBU);
+       clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI);
+       clkdev_add_pmu("1e100400.serial", NULL, 0, 0, PMU_ASC0);
+       clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT);
+       clkdev_add_pmu("1e100bb0.stp", NULL, 1, 0, PMU_STP);
+       clkdev_add_pmu("1e104100.dma", NULL, 1, 0, PMU_DMA);
+       clkdev_add_pmu("1e100800.spi", NULL, 1, 0, PMU_SPI);
+       clkdev_add_pmu("1e105300.ebu", NULL, 0, 0, PMU_EBU);
        clkdev_add_clkout();
 
        /* add the soc dependent clocks */
@@ -346,14 +497,30 @@ void __init ltq_soc_init(void)
                ifccr = CGU_IFCCR_VR9;
                pcicr = CGU_PCICR_VR9;
        } else {
-               clkdev_add_pmu("1e180000.etop", NULL, 0, PMU_PPE);
+               clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE);
        }
 
        if (!of_machine_is_compatible("lantiq,ase")) {
-               clkdev_add_pmu("1e100c00.serial", NULL, 0, PMU_ASC1);
+               clkdev_add_pmu("1e100c00.serial", NULL, 0, 0, PMU_ASC1);
                clkdev_add_pci();
        }
 
+       if (of_machine_is_compatible("lantiq,grx390") ||
+           of_machine_is_compatible("lantiq,ar10")) {
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 2, PMU_ANALOG_USB0_P);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 2, PMU_ANALOG_USB1_P);
+               /* rc 0 */
+               clkdev_add_pmu("1d900000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE0_P);
+               clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+               clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+               clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+               /* rc 1 */
+               clkdev_add_pmu("19000000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE1_P);
+               clkdev_add_pmu("19000000.pcie", "msi", 1, 1, PMU1_PCIE1_MSI);
+               clkdev_add_pmu("19000000.pcie", "pdi", 1, 1, PMU1_PCIE1_PDI);
+               clkdev_add_pmu("19000000.pcie", "ctl", 1, 1, PMU1_PCIE1_CTL);
+       }
+
        if (of_machine_is_compatible("lantiq,ase")) {
                if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
                        clkdev_add_static(CLOCK_266M, CLOCK_133M,
@@ -361,28 +528,84 @@ void __init ltq_soc_init(void)
                else
                        clkdev_add_static(CLOCK_133M, CLOCK_133M,
                                                CLOCK_133M, CLOCK_133M);
-               clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY),
-               clkdev_add_pmu("1e180000.etop", "ephy", 0, PMU_EPHY);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE);
+               clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY);
+               clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+       } else if (of_machine_is_compatible("lantiq,grx390")) {
+               clkdev_add_static(ltq_grx390_cpu_hz(), ltq_grx390_fpi_hz(),
+                                 ltq_grx390_fpi_hz(), ltq_grx390_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               /* rc 2 */
+               clkdev_add_pmu("1a800000.pcie", "phy", 1, 2, PMU_ANALOG_PCIE2_P);
+               clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
+               clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
+               clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH | PMU_PPE_DP);
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+       } else if (of_machine_is_compatible("lantiq,ar10")) {
+               clkdev_add_static(ltq_ar10_cpu_hz(), ltq_ar10_fpi_hz(),
+                                 ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0, PMU_SWITCH |
+                              PMU_PPE_DP | PMU_PPE_TC);
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
        } else if (of_machine_is_compatible("lantiq,vr9")) {
                clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
                                ltq_vr9_fpi_hz(), ltq_vr9_pp32_hz());
-               clkdev_add_pmu("1d900000.pcie", "phy", 1, PMU1_PCIE_PHY);
-               clkdev_add_pmu("1d900000.pcie", "bus", 0, PMU_PCIE_CLK);
-               clkdev_add_pmu("1d900000.pcie", "msi", 1, PMU1_PCIE_MSI);
-               clkdev_add_pmu("1d900000.pcie", "pdi", 1, PMU1_PCIE_PDI);
-               clkdev_add_pmu("1d900000.pcie", "ctl", 1, PMU1_PCIE_CTL);
-               clkdev_add_pmu("1d900000.pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
-               clkdev_add_pmu("1e108000.eth", NULL, 0,
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0 | PMU_AHBM);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1 | PMU_AHBM);
+               clkdev_add_pmu("1d900000.pcie", "phy", 1, 1, PMU1_PCIE_PHY);
+               clkdev_add_pmu("1d900000.pcie", "bus", 1, 0, PMU_PCIE_CLK);
+               clkdev_add_pmu("1d900000.pcie", "msi", 1, 1, PMU1_PCIE_MSI);
+               clkdev_add_pmu("1d900000.pcie", "pdi", 1, 1, PMU1_PCIE_PDI);
+               clkdev_add_pmu("1d900000.pcie", "ctl", 1, 1, PMU1_PCIE_CTL);
+               clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
+
+               clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
+               clkdev_add_pmu("1e108000.eth", NULL, 1, 0,
                                PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
                                PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
                                PMU_PPE_QSB | PMU_PPE_TOP);
-               clkdev_add_pmu("1f203000.rcu", "gphy", 0, PMU_GPHY);
+               clkdev_add_pmu("1f203000.rcu", "gphy", 1, 0, PMU_GPHY);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
        } else if (of_machine_is_compatible("lantiq,ar9")) {
                clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
                                ltq_ar9_fpi_hz(), CLOCK_250M);
-               clkdev_add_pmu("1e180000.etop", "switch", 0, PMU_SWITCH);
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e106000.usb", "ctl", 1, 0, PMU_USB1);
+               clkdev_add_pmu("1e106000.usb", "phy", 1, 0, PMU_USB1_P);
+               clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+               clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
        } else {
                clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
                                ltq_danube_fpi_hz(), ltq_danube_pp32_hz());
+               clkdev_add_pmu("1e101000.usb", "ctl", 1, 0, PMU_USB0);
+               clkdev_add_pmu("1e101000.usb", "phy", 1, 0, PMU_USB0_P);
+               clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
+               clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
+               clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
+               clkdev_add_pmu("1e100400.serial", NULL, 1, 0, PMU_ASC0);
        }
+
+       if (of_machine_is_compatible("lantiq,vr9"))
+               xbar_fpi_burst_disable();
 }
index 1e9e900cd3c382a4a8c3bce2ab7ca2987a1acfcd..0344e575f522982dc4725479d66544d79837b0b4 100644 (file)
@@ -15,4 +15,4 @@ obj-$(CONFIG_CPU_R3000)               += r3k_dump_tlb.o
 obj-$(CONFIG_CPU_TX39XX)       += r3k_dump_tlb.o
 
 # libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c
new file mode 100644 (file)
index 0000000..77e5f9c
--- /dev/null
@@ -0,0 +1,15 @@
+#include <linux/module.h>
+
+unsigned long long __bswapdi2(unsigned long long u)
+{
+       return (((u) & 0xff00000000000000ull) >> 56) |
+              (((u) & 0x00ff000000000000ull) >> 40) |
+              (((u) & 0x0000ff0000000000ull) >> 24) |
+              (((u) & 0x000000ff00000000ull) >>  8) |
+              (((u) & 0x00000000ff000000ull) <<  8) |
+              (((u) & 0x0000000000ff0000ull) << 24) |
+              (((u) & 0x000000000000ff00ull) << 40) |
+              (((u) & 0x00000000000000ffull) << 56);
+}
+
+EXPORT_SYMBOL(__bswapdi2);
diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c
new file mode 100644 (file)
index 0000000..2b302ff
--- /dev/null
@@ -0,0 +1,11 @@
+#include <linux/module.h>
+
+unsigned int __bswapsi2(unsigned int u)
+{
+       return (((u) & 0xff000000) >> 24) |
+              (((u) & 0x00ff0000) >>  8) |
+              (((u) & 0x0000ff00) <<  8) |
+              (((u) & 0x000000ff) << 24);
+}
+
+EXPORT_SYMBOL(__bswapsi2);
index 497912b38d8ebd82458f225a8b1fc2a5cbaf0d13..8e6e292675b24525f3b50e14e4214fe251914ae1 100644 (file)
@@ -120,11 +120,6 @@ config RS780_HPET
 
          If unsure, say Yes.
 
-config LOONGSON_SUSPEND
-       bool
-       default y
-       depends on CPU_SUPPORTS_CPUFREQ && SUSPEND
-
 config LOONGSON_UART_BASE
        bool
        default y
index f2e8153e44f536213e196002f005bb86da9ef72f..074d9cb15cd20dcb5551a65d99464bc0d0588992 100644 (file)
@@ -23,7 +23,7 @@ obj-$(CONFIG_CS5536) += cs5536/
 # Suspend Support
 #
 
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
 
 #
 # Big Memory (SWIOTLB) Support
index 4f9eaa328a1601a3ff63beaf14b86b65f960a469..08b8abcbfef537f11bd7a1c2a747665070bc9bf7 100644 (file)
@@ -8,4 +8,4 @@ obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
 # Suspend Support
 #
 
-obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+obj-$(CONFIG_SUSPEND) += pm.o
index 506a67a98cdf5cadf12420c17bb89ef4d4af41d9..be650ed7db596bb8b586c7b65bfdddce56f65b3b 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/init.h>
 #include <linux/percpu.h>
 #include <linux/types.h>
+#include <asm/debug.h>
 #include <asm/fpu_emulator.h>
 #include <asm/local.h>
 
@@ -27,7 +28,6 @@ static int fpuemu_stat_get(void *data, u64 *val)
 }
 DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
 
-extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_fpuemu(void)
 {
        struct dentry *d, *dir;
index 67ede4ef9b8d62c2e0db236fc5890914cebe4ee0..b4c64bd3f723903296c73d75dba3c3e29b861591 100644 (file)
@@ -28,3 +28,4 @@ obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
 obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
 obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
 obj-$(CONFIG_MIPS_CPU_SCACHE)  += sc-mips.o
+obj-$(CONFIG_SCACHE_DEBUGFS)   += sc-debugfs.o
diff --git a/arch/mips/mm/sc-debugfs.c b/arch/mips/mm/sc-debugfs.c
new file mode 100644 (file)
index 0000000..5eefe32
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bcache.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+
+static ssize_t sc_prefetch_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos)
+{
+       bool enabled = bc_prefetch_is_enabled();
+       char buf[3];
+
+       buf[0] = enabled ? 'Y' : 'N';
+       buf[1] = '\n';
+       buf[2] = 0;
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t sc_prefetch_write(struct file *file,
+                                const char __user *user_buf,
+                                size_t count, loff_t *ppos)
+{
+       char buf[32];
+       ssize_t buf_size;
+       bool enabled;
+       int err;
+
+       buf_size = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+       err = strtobool(buf, &enabled);
+       if (err)
+               return err;
+
+       if (enabled)
+               bc_prefetch_enable();
+       else
+               bc_prefetch_disable();
+
+       return count;
+}
+
+static const struct file_operations sc_prefetch_fops = {
+       .open = simple_open,
+       .llseek = default_llseek,
+       .read = sc_prefetch_read,
+       .write = sc_prefetch_write,
+};
+
+static int __init sc_debugfs_init(void)
+{
+       struct dentry *dir, *file;
+
+       if (!mips_debugfs_dir)
+               return -ENODEV;
+
+       dir = debugfs_create_dir("l2cache", mips_debugfs_dir);
+       if (IS_ERR(dir))
+               return PTR_ERR(dir);
+
+       file = debugfs_create_file("prefetch", S_IRUGO | S_IWUSR, dir,
+                                  NULL, &sc_prefetch_fops);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       return 0;
+}
+late_initcall(sc_debugfs_init);
index 53ea8391f9bbf9c2ddf81a114e59f52d05ad7abf..3bd0597d9c3da3a56ea6ba083ca05c67bd71c5e7 100644 (file)
@@ -51,11 +51,69 @@ static void mips_sc_disable(void)
        /* L2 cache is permanently enabled */
 }
 
+static void mips_sc_prefetch_enable(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return;
+
+       /*
+        * If there is one or more L2 prefetch unit present then enable
+        * prefetching for both code & data, for all ports.
+        */
+       pftctl = read_gcr_l2_pft_control();
+       if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) {
+               pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+               pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
+               pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+               write_gcr_l2_pft_control(pftctl);
+
+               pftctl = read_gcr_l2_pft_control_b();
+               pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+               pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+               write_gcr_l2_pft_control_b(pftctl);
+       }
+}
+
+static void mips_sc_prefetch_disable(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return;
+
+       pftctl = read_gcr_l2_pft_control();
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
+       write_gcr_l2_pft_control(pftctl);
+
+       pftctl = read_gcr_l2_pft_control_b();
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
+       pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
+       write_gcr_l2_pft_control_b(pftctl);
+}
+
+static bool mips_sc_prefetch_is_enabled(void)
+{
+       unsigned long pftctl;
+
+       if (mips_cm_revision() < CM_REV_CM2_5)
+               return false;
+
+       pftctl = read_gcr_l2_pft_control();
+       if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK))
+               return false;
+       return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK);
+}
+
 static struct bcache_ops mips_sc_ops = {
        .bc_enable = mips_sc_enable,
        .bc_disable = mips_sc_disable,
        .bc_wback_inv = mips_sc_wback_inv,
-       .bc_inv = mips_sc_inv
+       .bc_inv = mips_sc_inv,
+       .bc_prefetch_enable = mips_sc_prefetch_enable,
+       .bc_prefetch_disable = mips_sc_prefetch_disable,
+       .bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled,
 };
 
 /*
@@ -162,13 +220,13 @@ static inline int __init mips_sc_probe(void)
                return 0;
 
        tmp = (config2 >> 8) & 0x0f;
-       if (0 <= tmp && tmp <= 7)
+       if (tmp <= 7)
                c->scache.sets = 64 << tmp;
        else
                return 0;
 
        tmp = (config2 >> 0) & 0x0f;
-       if (0 <= tmp && tmp <= 7)
+       if (tmp <= 7)
                c->scache.ways = tmp + 1;
        else
                return 0;
@@ -186,6 +244,7 @@ int mips_sc_init(void)
        int found = mips_sc_probe();
        if (found) {
                mips_sc_enable();
+               mips_sc_prefetch_enable();
                bcops = &mips_sc_ops;
        }
        return found;
index 323d1d302f2bd898372c5143c1b8c7fb2714a1ad..32e0be27673fefbeca6839929e61a581c8980902 100644 (file)
@@ -311,6 +311,7 @@ static struct uasm_label labels[128];
 static struct uasm_reloc relocs[128];
 
 static int check_for_high_segbits;
+static bool fill_includes_sw_bits;
 
 static unsigned int kscratch_used_mask;
 
@@ -630,8 +631,14 @@ static void build_tlb_write_entry(u32 **p, struct uasm_label **l,
 static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
                                                        unsigned int reg)
 {
-       if (cpu_has_rixi) {
-               UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+       if (cpu_has_rixi && _PAGE_NO_EXEC) {
+               if (fill_includes_sw_bits) {
+                       UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
+               } else {
+                       UASM_i_SRL(p, reg, reg, ilog2(_PAGE_NO_EXEC));
+                       UASM_i_ROTR(p, reg, reg,
+                                   ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
+               }
        } else {
 #ifdef CONFIG_PHYS_ADDR_T_64BIT
                uasm_i_dsrl_safe(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -1005,21 +1012,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
         * 64bit address support (36bit on a 32bit CPU) in a 32bit
         * Kernel is a special case. Only a few CPUs use it.
         */
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-       if (cpu_has_64bits) {
-               uasm_i_ld(p, tmp, 0, ptep); /* get even pte */
-               uasm_i_ld(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
-               if (cpu_has_rixi) {
-                       UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-                       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-                       UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
-               } else {
-                       uasm_i_dsrl_safe(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
-                       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-                       uasm_i_dsrl_safe(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
-               }
-               UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
-       } else {
+       if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
                int pte_off_even = sizeof(pte_t) / 2;
                int pte_off_odd = pte_off_even + sizeof(pte_t);
 #ifdef CONFIG_XPA
@@ -1043,31 +1036,23 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
                uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
                uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
 #endif
+               return;
        }
-#else
+
        UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
        UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
        if (r45k_bvahwbug())
                build_tlb_probe_entry(p);
-       if (cpu_has_rixi) {
-               UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-               if (r4k_250MHZhwbug())
-                       UASM_i_MTC0(p, 0, C0_ENTRYLO0);
-               UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-               UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
-       } else {
-               UASM_i_SRL(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); /* convert to entrylo0 */
-               if (r4k_250MHZhwbug())
-                       UASM_i_MTC0(p, 0, C0_ENTRYLO0);
-               UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
-               UASM_i_SRL(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); /* convert to entrylo1 */
-               if (r45k_bvahwbug())
-                       uasm_i_mfc0(p, tmp, C0_INDEX);
-       }
+       build_convert_pte_to_entrylo(p, tmp);
+       if (r4k_250MHZhwbug())
+               UASM_i_MTC0(p, 0, C0_ENTRYLO0);
+       UASM_i_MTC0(p, tmp, C0_ENTRYLO0); /* load it */
+       build_convert_pte_to_entrylo(p, ptep);
+       if (r45k_bvahwbug())
+               uasm_i_mfc0(p, tmp, C0_INDEX);
        if (r4k_250MHZhwbug())
                UASM_i_MTC0(p, 0, C0_ENTRYLO1);
        UASM_i_MTC0(p, ptep, C0_ENTRYLO1); /* load it */
-#endif
 }
 
 struct mips_huge_tlb_info {
@@ -2299,6 +2284,10 @@ static void config_htw_params(void)
        /* re-initialize the PTI field including the even/odd bit */
        pwfield &= ~MIPS_PWFIELD_PTI_MASK;
        pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+       if (CONFIG_PGTABLE_LEVELS >= 3) {
+               pwfield &= ~MIPS_PWFIELD_MDI_MASK;
+               pwfield |= PMD_SHIFT << MIPS_PWFIELD_MDI_SHIFT;
+       }
        /* Set the PTEI right shift */
        ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
        pwfield |= ptei;
@@ -2320,9 +2309,11 @@ static void config_htw_params(void)
 
        pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
        pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+       if (CONFIG_PGTABLE_LEVELS >= 3)
+               pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
 
        /* If XPA has been enabled, PTEs are 64-bit in size. */
-       if (read_c0_pagegrain() & PG_ELPA)
+       if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
                pwsize |= 1;
 
        write_c0_pwsize(pwsize);
@@ -2360,6 +2351,41 @@ static void config_xpa_params(void)
 #endif
 }
 
+static void check_pabits(void)
+{
+       unsigned long entry;
+       unsigned pabits, fillbits;
+
+       if (!cpu_has_rixi || !_PAGE_NO_EXEC) {
+               /*
+                * We'll only be making use of the fact that we can rotate bits
+                * into the fill if the CPU supports RIXI, so don't bother
+                * probing this for CPUs which don't.
+                */
+               return;
+       }
+
+       write_c0_entrylo0(~0ul);
+       back_to_back_c0_hazard();
+       entry = read_c0_entrylo0();
+
+       /* clear all non-PFN bits */
+       entry &= ~((1 << MIPS_ENTRYLO_PFN_SHIFT) - 1);
+       entry &= ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
+
+       /* find a lower bound on PABITS, and upper bound on fill bits */
+       pabits = fls_long(entry) + 6;
+       fillbits = max_t(int, (int)BITS_PER_LONG - pabits, 0);
+
+       /* minus the RI & XI bits */
+       fillbits -= min_t(unsigned, fillbits, 2);
+
+       if (fillbits >= ilog2(_PAGE_NO_EXEC))
+               fill_includes_sw_bits = true;
+
+       pr_debug("Entry* registers contain %u fill bits\n", fillbits);
+}
+
 void build_tlb_refill_handler(void)
 {
        /*
@@ -2370,6 +2396,7 @@ void build_tlb_refill_handler(void)
        static int run_once = 0;
 
        output_pgtable_bits_defines();
+       check_pabits();
 
 #ifdef CONFIG_64BIT
        check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
index ea35587a5c2920a0e32c4a00fdc346ac41d4cd9d..5827af77c18e9931c43af5e5df2881f94df44c25 100644 (file)
@@ -5,9 +5,18 @@
 # Copyright (C) 2008 Wind River Systems, Inc.
 #   written by Ralf Baechle <ralf@linux-mips.org>
 #
-obj-y                          := malta-display.o malta-dt.o malta-init.o \
-                                  malta-int.o malta-memory.o malta-platform.o \
-                                  malta-reset.o malta-setup.o malta-time.o
+obj-y                          += malta-display.o
+obj-y                          += malta-dt.o
+obj-y                          += malta-dtshim.o
+obj-y                          += malta-init.o
+obj-y                          += malta-int.o
+obj-y                          += malta-memory.o
+obj-y                          += malta-platform.o
+obj-y                          += malta-reset.o
+obj-y                          += malta-setup.o
+obj-y                          += malta-time.o
 
 obj-$(CONFIG_MIPS_CMP)         += malta-amon.o
 obj-$(CONFIG_MIPS_MALTA_PM)    += malta-pm.o
+
+CFLAGS_malta-dtshim.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
new file mode 100644 (file)
index 0000000..f7133ef
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sizes.h>
+#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
+#include <asm/page.h>
+
+static unsigned char fdt_buf[16 << 10] __initdata;
+
+/* determined physical memory size, not overridden by command line args         */
+extern unsigned long physical_memsize;
+
+#define MAX_MEM_ARRAY_ENTRIES 1
+
+static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
+{
+       unsigned long size_preio;
+       unsigned entries;
+
+       entries = 1;
+       mem_array[0] = cpu_to_be32(PHYS_OFFSET);
+       if (config_enabled(CONFIG_EVA)) {
+               /*
+                * The current Malta EVA configuration is "special" in that it
+                * always makes use of addresses in the upper half of the 32 bit
+                * physical address map, which gives it a contiguous region of
+                * DDR but limits it to 2GB.
+                */
+               mem_array[1] = cpu_to_be32(size);
+       } else {
+               size_preio = min_t(unsigned long, size, SZ_256M);
+               mem_array[1] = cpu_to_be32(size_preio);
+       }
+
+       BUG_ON(entries > MAX_MEM_ARRAY_ENTRIES);
+       return entries;
+}
+
+static void __init append_memory(void *fdt, int root_off)
+{
+       __be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
+       unsigned long memsize;
+       unsigned mem_entries;
+       int i, err, mem_off;
+       char *var, param_name[10], *var_names[] = {
+               "ememsize", "memsize",
+       };
+
+       /* if a memory node already exists, leave it alone */
+       mem_off = fdt_path_offset(fdt, "/memory");
+       if (mem_off >= 0)
+               return;
+
+       /* find memory size from the bootloader environment */
+       for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+               var = fw_getenv(var_names[i]);
+               if (!var)
+                       continue;
+
+               err = kstrtoul(var, 0, &physical_memsize);
+               if (!err)
+                       break;
+
+               pr_warn("Failed to read the '%s' env variable '%s'\n",
+                       var_names[i], var);
+       }
+
+       if (!physical_memsize) {
+               pr_warn("The bootloader didn't provide memsize: defaulting to 32MB\n");
+               physical_memsize = 32 << 20;
+       }
+
+       if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
+               /*
+                * SOC-it swaps, or perhaps doesn't swap, when DMA'ing
+                * the last word of physical memory.
+                */
+               physical_memsize -= PAGE_SIZE;
+       }
+
+       /* default to using all available RAM */
+       memsize = physical_memsize;
+
+       /* allow the user to override the usable memory */
+       for (i = 0; i < ARRAY_SIZE(var_names); i++) {
+               snprintf(param_name, sizeof(param_name), "%s=", var_names[i]);
+               var = strstr(arcs_cmdline, param_name);
+               if (!var)
+                       continue;
+
+               memsize = memparse(var + strlen(param_name), NULL);
+       }
+
+       /* if the user says there's more RAM than we thought, believe them */
+       physical_memsize = max_t(unsigned long, physical_memsize, memsize);
+
+       /* append memory to the DT */
+       mem_off = fdt_add_subnode(fdt, root_off, "memory");
+       if (mem_off < 0)
+               panic("Unable to add memory node to DT: %d", mem_off);
+
+       err = fdt_setprop_string(fdt, mem_off, "device_type", "memory");
+       if (err)
+               panic("Unable to set memory node device_type: %d", err);
+
+       mem_entries = gen_fdt_mem_array(mem_array, physical_memsize);
+       err = fdt_setprop(fdt, mem_off, "reg", mem_array,
+                         mem_entries * 2 * sizeof(mem_array[0]));
+       if (err)
+               panic("Unable to set memory regs property: %d", err);
+
+       mem_entries = gen_fdt_mem_array(mem_array, memsize);
+       err = fdt_setprop(fdt, mem_off, "linux,usable-memory", mem_array,
+                         mem_entries * 2 * sizeof(mem_array[0]));
+       if (err)
+               panic("Unable to set linux,usable-memory property: %d", err);
+}
+
+void __init *malta_dt_shim(void *fdt)
+{
+       int root_off, len, err;
+       const char *compat;
+
+       if (fdt_check_header(fdt))
+               panic("Corrupt DT");
+
+       err = fdt_open_into(fdt, fdt_buf, sizeof(fdt_buf));
+       if (err)
+               panic("Unable to open FDT: %d", err);
+
+       root_off = fdt_path_offset(fdt_buf, "/");
+       if (root_off < 0)
+               panic("No / node in DT");
+
+       compat = fdt_getprop(fdt_buf, root_off, "compatible", &len);
+       if (!compat)
+               panic("No root compatible property in DT: %d", len);
+
+       /* if this isn't Malta, leave the DT alone */
+       if (strncmp(compat, "mti,malta", len))
+               return fdt;
+
+       append_memory(fdt_buf, root_off);
+
+       err = fdt_pack(fdt_buf);
+       if (err)
+               panic("Unable to pack FDT: %d\n", err);
+
+       return fdt_buf;
+}
index 53c24784a2f7bd2e8c0ae719f1f07c9ad60dd52b..571148c5fd0baa5ce8656e87574144d90b58e346 100644 (file)
@@ -302,6 +302,7 @@ void __init prom_init(void)
                return;
        if (!register_vsmp_smp_ops())
                return;
+       register_up_smp_ops();
 }
 
 void platform_early_l2_init(void)
index dadeb83791828249e3af6d62ad55f1e9a2756a8a..d5f8dae6a7978a5b7e3c62c4c70bef756941a061 100644 (file)
 #include <asm/sections.h>
 #include <asm/fw/fw.h>
 
-static fw_memblock_t mdesc[FW_MAX_MEMBLOCKS];
-
 /* determined physical memory size, not overridden by command line args         */
 unsigned long physical_memsize = 0L;
 
-fw_memblock_t * __init fw_getmdesc(int eva)
-{
-       char *memsize_str, *ememsize_str = NULL, *ptr;
-       unsigned long memsize = 0, ememsize = 0;
-       static char cmdline[COMMAND_LINE_SIZE] __initdata;
-       int tmp;
-
-       /* otherwise look in the environment */
-
-       memsize_str = fw_getenv("memsize");
-       if (memsize_str) {
-               tmp = kstrtoul(memsize_str, 0, &memsize);
-               if (tmp)
-                       pr_warn("Failed to read the 'memsize' env variable.\n");
-       }
-       if (eva) {
-       /* Look for ememsize for EVA */
-               ememsize_str = fw_getenv("ememsize");
-               if (ememsize_str) {
-                       tmp = kstrtoul(ememsize_str, 0, &ememsize);
-                       if (tmp)
-                               pr_warn("Failed to read the 'ememsize' env variable.\n");
-               }
-       }
-       if (!memsize && !ememsize) {
-               pr_warn("memsize not set in YAMON, set to default (32Mb)\n");
-               physical_memsize = 0x02000000;
-       } else {
-               if (memsize > (256 << 20)) { /* memsize should be capped to 256M */
-                       pr_warn("Unsupported memsize value (0x%lx) detected! "
-                               "Using 0x10000000 (256M) instead\n",
-                               memsize);
-                       memsize = 256 << 20;
-               }
-               /* If ememsize is set, then set physical_memsize to that */
-               physical_memsize = ememsize ? : memsize;
-       }
-
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
-          word of physical memory */
-       physical_memsize -= PAGE_SIZE;
-#endif
-
-       /* Check the command line for a memsize directive that overrides
-          the physical/default amount */
-       strcpy(cmdline, arcs_cmdline);
-       ptr = strstr(cmdline, "memsize=");
-       if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
-               ptr = strstr(ptr, " memsize=");
-       /* And now look for ememsize */
-       if (eva) {
-               ptr = strstr(cmdline, "ememsize=");
-               if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
-                       ptr = strstr(ptr, " ememsize=");
-       }
-
-       if (ptr)
-               memsize = memparse(ptr + 8 + (eva ? 1 : 0), &ptr);
-       else
-               memsize = physical_memsize;
-
-       /* Last 64K for HIGHMEM arithmetics */
-       if (memsize > 0x7fff0000)
-               memsize = 0x7fff0000;
-
-       memset(mdesc, 0, sizeof(mdesc));
-
-       mdesc[0].type = fw_dontuse;
-       mdesc[0].base = PHYS_OFFSET;
-       mdesc[0].size = 0x00001000;
-
-       mdesc[1].type = fw_code;
-       mdesc[1].base = mdesc[0].base + 0x00001000UL;
-       mdesc[1].size = 0x000ef000;
-
-       /*
-        * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
-        * south bridge and PCI access always forwarded to the ISA Bus and
-        * BIOSCS# is always generated.
-        * This mean that this area can't be used as DMA memory for PCI
-        * devices.
-        */
-       mdesc[2].type = fw_dontuse;
-       mdesc[2].base = mdesc[0].base + 0x000f0000UL;
-       mdesc[2].size = 0x00010000;
-
-       mdesc[3].type = fw_dontuse;
-       mdesc[3].base = mdesc[0].base + 0x00100000UL;
-       mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
-               0x00100000UL;
-
-       mdesc[4].type = fw_free;
-       mdesc[4].base = mdesc[0].base + CPHYSADDR(PFN_ALIGN(&_end));
-       mdesc[4].size = memsize - CPHYSADDR(mdesc[4].base);
-
-       return &mdesc[0];
-}
-
 static void free_init_pages_eva_malta(void *begin, void *end)
 {
        free_init_pages("unused kernel", __pa_symbol((unsigned long *)begin),
                        __pa_symbol((unsigned long *)end));
 }
 
-static int __init fw_memtype_classify(unsigned int type)
-{
-       switch (type) {
-       case fw_free:
-               return BOOT_MEM_RAM;
-       case fw_code:
-               return BOOT_MEM_ROM_DATA;
-       default:
-               return BOOT_MEM_RESERVED;
-       }
-}
-
 void __init fw_meminit(void)
 {
-       fw_memblock_t *p;
-
-       p = fw_getmdesc(config_enabled(CONFIG_EVA));
-       free_init_pages_eva = (config_enabled(CONFIG_EVA) ?
-                              free_init_pages_eva_malta : NULL);
+       bool eva = config_enabled(CONFIG_EVA);
 
-       while (p->size) {
-               long type;
-               unsigned long base, size;
-
-               type = fw_memtype_classify(p->type);
-               base = p->base;
-               size = p->size;
-
-               add_memory_region(base, size, type);
-               p++;
-       }
+       free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
 }
 
 void __init prom_free_prom_memory(void)
index 9d1e7f5ec36cac95dbad432f0a8c1378b5c75195..4740c82fb97a14e95118d05590b66b3192e9f1f5 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/time.h>
 
 #include <asm/fw/fw.h>
+#include <asm/mach-malta/malta-dtshim.h>
 #include <asm/mips-cm.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/malta.h>
@@ -250,8 +251,10 @@ static void __init bonito_quirks_setup(void)
 void __init plat_mem_setup(void)
 {
        unsigned int i;
+       void *fdt = __dtb_start;
 
-       __dt_setup_arch(__dtb_start);
+       fdt = malta_dt_shim(fdt);
+       __dt_setup_arch(fdt);
 
        if (config_enabled(CONFIG_EVA))
                /* EVA has already been configured in mach-malta/kernel-init.h */
index a625bdb6d6aa0e2f23de8c629f34e28803d19d66..856a6e6d296e978a6435707a781bc15df412824e 100644 (file)
@@ -87,7 +87,6 @@ void __init *xlp_dt_init(void *fdtp)
 void __init xlp_early_init_devtree(void)
 {
        __dt_setup_arch(xlp_fdt_blob);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 }
 
 void __init device_tree_init(void)
index ed6732f9aa874c2557a93de78e9cb1c816320af1..53a42b07008b99f2043ac1da444b9732c4af8c2b 100644 (file)
@@ -432,8 +432,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
 
        /* find the interrupt controller child node */
        for_each_child_of_node(np, child) {
-               if (of_get_property(child, "interrupt-controller", NULL) &&
-                   of_node_get(child)) {
+               if (of_get_property(child, "interrupt-controller", NULL)) {
                        rpc->intc_of_node = child;
                        break;
                }
@@ -449,8 +448,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
        /* find the PCI host bridge child node */
        for_each_child_of_node(np, child) {
                if (child->type &&
-                   of_node_cmp(child->type, "pci") == 0 &&
-                   of_node_get(child)) {
+                   of_node_cmp(child->type, "pci") == 0) {
                        rpc->pci_controller.of_node = child;
                        break;
                }
index 8bd8ebb20a72631501e5365478d10aa0d07b992b..96ba2cc9ad3e34da3948c3103d41629e24c88227 100644 (file)
@@ -58,7 +58,6 @@ void __init plat_mem_setup(void)
                panic("Device-tree not present");
 
        __dt_setup_arch((void *)fw_arg1);
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
        plat_setup_iocoherency();
 }
index a8e70a9f274bdf70b0be449bee57c71c513e6fc4..e46f91f971c54f85759067c26b8a5d27d98f6a74 100644 (file)
@@ -48,7 +48,7 @@ static int systick_next_event(unsigned long delta,
        sdev = container_of(evt, struct systick_device, dev);
        count = ioread32(sdev->membase + SYSTICK_COUNT);
        count = (count + delta) % SYSTICK_FREQ;
-       iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE);
+       iowrite32(count, sdev->membase + SYSTICK_COMPARE);
 
        return 0;
 }
index 255d695ec8c609168e92d1b9ec5cafe5020eda1b..3c59ffe5f5f54116785a501ad39abaccd1ad11a5 100644 (file)
 #define MT7628_CHIP_NAME1      0x20203832
 
 #define UART_REG_TX            0x04
+#define UART_REG_LCR           0x0c
 #define UART_REG_LSR           0x14
 #define UART_REG_LSR_RT2880    0x1c
 
 static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE);
 static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE);
+static int init_complete;
 
 static inline void uart_w32(u32 val, unsigned reg)
 {
@@ -47,8 +49,32 @@ static inline int soc_is_mt7628(void)
                (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1);
 }
 
+static void find_uart_base(void)
+{
+       int i;
+
+       if (!soc_is_mt7628())
+               return;
+
+       for (i = 0; i < 3; i++) {
+               u32 reg = uart_r32(UART_REG_LCR + (0x100 * i));
+
+               if (!reg)
+                       continue;
+
+               uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE +
+                                                         (0x100 * i));
+               break;
+       }
+}
+
 void prom_putchar(unsigned char ch)
 {
+       if (!init_complete) {
+               find_uart_base();
+               init_complete = 1;
+       }
+
        if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) {
                uart_w32(ch, UART_TX);
                while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
index 2ea5ff6dc22e6d769cc851347b5c7492535e0596..dfb04fcedb042d9b80621ac3197886a1ea3bccda 100644 (file)
 #define PMU1_CFG               0x8C
 #define DIG_SW_SEL             BIT(25)
 
-/* is this a MT7620 or a MT7628 */
-enum mt762x_soc_type mt762x_soc;
+/* clock scaling */
+#define CLKCFG_FDIV_MASK       0x1f00
+#define CLKCFG_FDIV_USB_VAL    0x0300
+#define CLKCFG_FFRAC_MASK      0x001f
+#define CLKCFG_FFRAC_USB_VAL   0x0003
+
+/* EFUSE bits */
+#define EFUSE_MT7688           0x100000
+
+/* DRAM type bit */
+#define DRAM_TYPE_MT7628_MASK  0x1
 
 /* does the board have sdram or ddram */
 static int dram_type;
@@ -227,6 +236,12 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
        { 0 }
 };
 
+static inline int is_mt76x8(void)
+{
+       return ralink_soc == MT762X_SOC_MT7628AN ||
+              ralink_soc == MT762X_SOC_MT7688;
+}
+
 static __init u32
 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div)
 {
@@ -381,7 +396,7 @@ void __init ralink_clk_init(void)
 #define RINT(x)                ((x) / 1000000)
 #define RFRAC(x)       (((x) / 1000) % 1000)
 
-       if (mt762x_soc == MT762X_SOC_MT7628AN) {
+       if (is_mt76x8()) {
                if (xtal_rate == MHZ(40))
                        cpu_rate = MHZ(580);
                else
@@ -423,6 +438,20 @@ void __init ralink_clk_init(void)
        ralink_clk_add("10000b00.spi", sys_rate);
        ralink_clk_add("10000c00.uartlite", periph_rate);
        ralink_clk_add("10180000.wmac", xtal_rate);
+
+       if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) {
+               /*
+                * When the CPU goes into sleep mode, the BUS clock will be
+                * too low for USB to function properly. Adjust the busses
+                * fractional divider to fix this
+                */
+               u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG);
+
+               val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK);
+               val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL;
+
+               rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG);
+       }
 }
 
 void __init ralink_of_remap(void)
@@ -499,20 +528,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
 
        if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) {
                if (bga) {
-                       mt762x_soc = MT762X_SOC_MT7620A;
+                       ralink_soc = MT762X_SOC_MT7620A;
                        name = "MT7620A";
                        soc_info->compatible = "ralink,mt7620a-soc";
                } else {
-                       mt762x_soc = MT762X_SOC_MT7620N;
+                       ralink_soc = MT762X_SOC_MT7620N;
                        name = "MT7620N";
                        soc_info->compatible = "ralink,mt7620n-soc";
-#ifdef CONFIG_PCI
-                       panic("mt7620n is only supported for non pci kernels");
-#endif
                }
        } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) {
-               mt762x_soc = MT762X_SOC_MT7628AN;
-               name = "MT7628AN";
+               u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG);
+
+               if (efuse & EFUSE_MT7688) {
+                       ralink_soc = MT762X_SOC_MT7688;
+                       name = "MT7688";
+               } else {
+                       ralink_soc = MT762X_SOC_MT7628AN;
+                       name = "MT7628AN";
+               }
                soc_info->compatible = "ralink,mt7628an-soc";
        } else {
                panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
@@ -525,10 +558,14 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
                (rev & CHIP_REV_ECO_MASK));
 
        cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
-       dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK;
+       if (is_mt76x8())
+               dram_type = cfg0 & DRAM_TYPE_MT7628_MASK;
+       else
+               dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) &
+                           SYSCFG0_DRAM_TYPE_MASK;
 
        soc_info->mem_base = MT7620_DRAM_BASE;
-       if (mt762x_soc == MT762X_SOC_MT7628AN)
+       if (is_mt76x8())
                mt7628_dram_init(soc_info);
        else
                mt7620_dram_init(soc_info);
@@ -541,7 +578,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        pr_info("Digital PMU set to %s control\n",
                (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw"));
 
-       if (mt762x_soc == MT762X_SOC_MT7628AN)
+       if (is_mt76x8())
                rt2880_pinmux_data = mt7628an_pinmux_data;
        else
                rt2880_pinmux_data = mt7620a_pinmux_data;
index 0d30dcd6324623a3ed6dc635ec653a2619228132..f9eda5d8f82cd54681efbdf65c4f55123a3dfeed 100644 (file)
@@ -74,8 +74,6 @@ void __init plat_mem_setup(void)
         */
        __dt_setup_arch(__dtb_start);
 
-       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-
        of_scan_flat_dt(early_init_dt_find_memory, NULL);
        if (memory_dtb)
                of_scan_flat_dt(early_init_dt_scan_memory, NULL);
index 09419f67da3990985be6d0a4db5de6460def0607..39a9142f71be214ed97194edc15f0398a028ffbd 100644 (file)
 #include <asm/bootinfo.h>
 #include <asm/addrspace.h>
 
+#include <asm/mach-ralink/ralink_regs.h>
+
 #include "common.h"
 
 struct ralink_soc_info soc_info;
 struct rt2880_pmx_group *rt2880_pinmux_data = NULL;
 
+enum ralink_soc_type ralink_soc;
+EXPORT_SYMBOL_GPL(ralink_soc);
+
 const char *get_system_type(void)
 {
        return soc_info.sys_type;
index 55c7ec59df3cca8a73259ee84731189a91db49ce..ee117c4bc4a36cc6f974c5efc89751300a535108 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pm.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/delay.h>
 #include <linux/reset-controller.h>
 
 #include <asm/reboot.h>
 #include <asm/mach-ralink/ralink_regs.h>
 
 /* Reset Control */
-#define SYSC_REG_RESET_CTRL     0x034
-#define RSTCTL_RESET_SYSTEM     BIT(0)
+#define SYSC_REG_RESET_CTRL    0x034
+
+#define RSTCTL_RESET_PCI       BIT(26)
+#define RSTCTL_RESET_SYSTEM    BIT(0)
 
 static int ralink_assert_device(struct reset_controller_dev *rcdev,
                                unsigned long id)
@@ -83,6 +86,11 @@ void ralink_rst_init(void)
 
 static void ralink_restart(char *command)
 {
+       if (IS_ENABLED(CONFIG_PCI)) {
+               rt_sysc_m32(0, RSTCTL_RESET_PCI, SYSC_REG_RESET_CTRL);
+               mdelay(50);
+       }
+
        local_irq_disable();
        rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
        unreachable();
@@ -98,7 +106,6 @@ static int __init mips_reboot_setup(void)
 {
        _machine_restart = ralink_restart;
        _machine_halt = ralink_halt;
-       pm_power_off = ralink_halt;
 
        return 0;
 }
index 738cec865f41a1a371d1c5506f0c4e50b268dce6..844f5cd55c8f1c1e96e20db2a888c22e1fb12327 100644 (file)
@@ -119,4 +119,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
 
        rt2880_pinmux_data = rt2880_pinmux_data_act;
+       ralink_soc == RT2880_SOC;
 }
index c40776ab67db5e0147d250e83990f6577c693268..9e45725920650bd55350549097f9330403f3ef6a 100644 (file)
@@ -21,8 +21,6 @@
 
 #include "common.h"
 
-enum rt305x_soc_type rt305x_soc;
-
 static struct rt2880_pmx_func i2c_func[] =  { FUNC("i2c", 0, 1, 2) };
 static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) };
 static struct rt2880_pmx_func uartf_func[] = {
@@ -201,6 +199,7 @@ void __init ralink_clk_init(void)
        }
 
        ralink_clk_add("cpu", cpu_rate);
+       ralink_clk_add("sys", sys_rate);
        ralink_clk_add("10000b00.spi", sys_rate);
        ralink_clk_add("10000100.timer", wdt_rate);
        ralink_clk_add("10000120.watchdog", wdt_rate);
@@ -235,24 +234,24 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
 
                icache_sets = (read_c0_config1() >> 22) & 7;
                if (icache_sets == 1) {
-                       rt305x_soc = RT305X_SOC_RT3050;
+                       ralink_soc = RT305X_SOC_RT3050;
                        name = "RT3050";
                        soc_info->compatible = "ralink,rt3050-soc";
                } else {
-                       rt305x_soc = RT305X_SOC_RT3052;
+                       ralink_soc = RT305X_SOC_RT3052;
                        name = "RT3052";
                        soc_info->compatible = "ralink,rt3052-soc";
                }
        } else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT3350;
+               ralink_soc = RT305X_SOC_RT3350;
                name = "RT3350";
                soc_info->compatible = "ralink,rt3350-soc";
        } else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT3352;
+               ralink_soc = RT305X_SOC_RT3352;
                name = "RT3352";
                soc_info->compatible = "ralink,rt3352-soc";
        } else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) {
-               rt305x_soc = RT305X_SOC_RT5350;
+               ralink_soc = RT305X_SOC_RT5350;
                name = "RT5350";
                soc_info->compatible = "ralink,rt5350-soc";
        } else {
index 86a535c770d84e4768680b7a58e06acf97a247e8..582995aaaf4e7e8a9848c512d150b515f3628344 100644 (file)
@@ -153,4 +153,6 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
        soc_info->mem_size_max = RT3883_MEM_SIZE_MAX;
 
        rt2880_pinmux_data = rt3883_pinmux_data;
+
+       ralink_soc == RT3883_SOC;
 }
diff --git a/arch/mips/vdso/.gitignore b/arch/mips/vdso/.gitignore
new file mode 100644 (file)
index 0000000..5286a7d
--- /dev/null
@@ -0,0 +1,4 @@
+*.so*
+vdso-*image.c
+genvdso
+vdso*.lds
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
new file mode 100644 (file)
index 0000000..ef5f348
--- /dev/null
@@ -0,0 +1,160 @@
+# Objects to go into the VDSO.
+obj-vdso-y := elf.o gettimeofday.o sigreturn.o
+
+# Common compiler flags between ABIs.
+ccflags-vdso := \
+       $(filter -I%,$(KBUILD_CFLAGS)) \
+       $(filter -E%,$(KBUILD_CFLAGS)) \
+       $(filter -march=%,$(KBUILD_CFLAGS))
+cflags-vdso := $(ccflags-vdso) \
+       $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
+       -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+       $(call cc-option, -fno-stack-protector)
+aflags-vdso := $(ccflags-vdso) \
+       $(filter -I%,$(KBUILD_CFLAGS)) \
+       $(filter -E%,$(KBUILD_CFLAGS)) \
+       -D__ASSEMBLY__ -Wa,-gdwarf-2
+
+#
+# For the pre-R6 code in arch/mips/vdso/vdso.h for locating
+# the base address of VDSO, the linker will emit a R_MIPS_PC32
+# relocation in binutils > 2.25 but it will fail with older versions
+# because that relocation is not supported for that symbol. As a result
+# of which we are forced to disable the VDSO symbols when building
+# with < 2.25 binutils on pre-R6 kernels. For more references on why we
+# can't use other methods to get the base address of VDSO please refer to
+# the comments on that file.
+#
+ifndef CONFIG_CPU_MIPSR6
+  ifeq ($(call ld-ifversion, -gt, 22400000, y),)
+    $(warning MIPS VDSO requires binutils > 2.24)
+    obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
+    ccflags-vdso += -DDISABLE_MIPS_VDSO
+  endif
+endif
+
+# VDSO linker flags.
+VDSO_LDFLAGS := \
+       -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
+       -nostdlib -shared \
+       $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+       $(call cc-ldoption, -Wl$(comma)--build-id)
+
+GCOV_PROFILE := n
+
+#
+# Shared build commands.
+#
+
+quiet_cmd_vdsold = VDSO    $@
+      cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
+                   -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
+
+hostprogs-y := genvdso
+
+quiet_cmd_genvdso = GENVDSO $@
+define cmd_genvdso
+       cp $< $(<:%.dbg=%) && \
+       $(OBJCOPY) -S $< $(<:%.dbg=%) && \
+       $(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
+endef
+
+#
+# Build native VDSO.
+#
+
+native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
+
+targets += $(obj-vdso-y)
+targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
+
+obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
+
+$(obj-vdso): KBUILD_CFLAGS := $(cflags-vdso) $(native-abi)
+$(obj-vdso): KBUILD_AFLAGS := $(aflags-vdso) $(native-abi)
+
+$(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
+
+$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-image.o
+
+#
+# Build O32 VDSO.
+#
+
+# Define these outside the ifdef to ensure they are picked up by clean.
+targets += $(obj-vdso-y:%.o=%-o32.o)
+targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
+
+ifdef CONFIG_MIPS32_O32
+
+obj-vdso-o32 := $(obj-vdso-y:%.o=$(obj)/%-o32.o)
+
+$(obj-vdso-o32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=32
+$(obj-vdso-o32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=32
+
+$(obj)/%-o32.o: $(src)/%.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+$(obj)/%-o32.o: $(src)/%.c FORCE
+       $(call cmd,force_checksrc)
+       $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
+       $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-o32-image.c: VDSO_NAME := o32
+$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-o32-image.o
+
+endif
+
+#
+# Build N32 VDSO.
+#
+
+targets += $(obj-vdso-y:%.o=%-n32.o)
+targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
+
+ifdef CONFIG_MIPS32_N32
+
+obj-vdso-n32 := $(obj-vdso-y:%.o=$(obj)/%-n32.o)
+
+$(obj-vdso-n32): KBUILD_CFLAGS := $(cflags-vdso) -mabi=n32
+$(obj-vdso-n32): KBUILD_AFLAGS := $(aflags-vdso) -mabi=n32
+
+$(obj)/%-n32.o: $(src)/%.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+$(obj)/%-n32.o: $(src)/%.c FORCE
+       $(call cmd,force_checksrc)
+       $(call if_changed_rule,cc_o_c)
+
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
+       $(call if_changed_dep,cpp_lds_S)
+
+$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
+       $(call if_changed,vdsold)
+
+$(obj)/vdso-n32-image.c: VDSO_NAME := n32
+$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
+       $(call if_changed,genvdso)
+
+obj-y += vdso-n32-image.o
+
+endif
+
+# FIXME: Need install rule for debug.
+# Needs to deal with dependency for generation of dbg by cmd_genvdso...
diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S
new file mode 100644 (file)
index 0000000..be37bbb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/elfnote.h>
+#include <linux/version.h>
+
+ELFNOTE_START(Linux, 0, "a")
+       .long LINUX_VERSION_CODE
+ELFNOTE_END
+
+/*
+ * The .MIPS.abiflags section must be defined with the FP ABI flags set
+ * to 'any' to be able to link with both old and new libraries.
+ * Newer toolchains are capable of automatically generating this, but we want
+ * to work with older toolchains as well. Therefore, we define the contents of
+ * this section here (under different names), and then genvdso will patch
+ * it to have the correct name and type.
+ *
+ * We base the .MIPS.abiflags section on preprocessor definitions rather than
+ * CONFIG_* because we need to match the particular ABI we are building the
+ * VDSO for.
+ *
+ * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
+ * for the .MIPS.abiflags section description.
+ */
+
+       .section .mips_abiflags, "a"
+       .align 3
+__mips_abiflags:
+       .hword  0               /* version */
+       .byte   __mips          /* isa_level */
+
+       /* isa_rev */
+#ifdef __mips_isa_rev
+       .byte   __mips_isa_rev
+#else
+       .byte   0
+#endif
+
+       /* gpr_size */
+#ifdef __mips64
+       .byte   2               /* AFL_REG_64 */
+#else
+       .byte   1               /* AFL_REG_32 */
+#endif
+
+       /* cpr1_size */
+#if (defined(__mips_isa_rev) && __mips_isa_rev >= 6) || defined(__mips64)
+       .byte   2               /* AFL_REG_64 */
+#else
+       .byte   1               /* AFL_REG_32 */
+#endif
+
+       .byte   0               /* cpr2_size (AFL_REG_NONE) */
+       .byte   0               /* fp_abi (Val_GNU_MIPS_ABI_FP_ANY) */
+       .word   0               /* isa_ext */
+       .word   0               /* ases */
+       .word   0               /* flags1 */
+       .word   0               /* flags2 */
diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c
new file mode 100644 (file)
index 0000000..530a36f
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * This tool is used to generate the real VDSO images from the raw image. It
+ * first patches up the MIPS ABI flags and GNU attributes sections defined in
+ * elf.S to have the correct name and type. It then generates a C source file
+ * to be compiled into the kernel containing the VDSO image data and a
+ * mips_vdso_image struct for it, including symbol offsets extracted from the
+ * image.
+ *
+ * We need to be passed both a stripped and unstripped VDSO image. The stripped
+ * image is compiled into the kernel, but we must also patch up the unstripped
+ * image's ABI flags sections so that it can be installed and used for
+ * debugging.
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <byteswap.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Define these in case the system elf.h is not new enough to have them. */
+#ifndef SHT_GNU_ATTRIBUTES
+# define SHT_GNU_ATTRIBUTES    0x6ffffff5
+#endif
+#ifndef SHT_MIPS_ABIFLAGS
+# define SHT_MIPS_ABIFLAGS     0x7000002a
+#endif
+
+enum {
+       ABI_O32 = (1 << 0),
+       ABI_N32 = (1 << 1),
+       ABI_N64 = (1 << 2),
+
+       ABI_ALL = ABI_O32 | ABI_N32 | ABI_N64,
+};
+
+/* Symbols the kernel requires offsets for. */
+static struct {
+       const char *name;
+       const char *offset_name;
+       unsigned int abis;
+} vdso_symbols[] = {
+       { "__vdso_sigreturn", "off_sigreturn", ABI_O32 },
+       { "__vdso_rt_sigreturn", "off_rt_sigreturn", ABI_ALL },
+       {}
+};
+
+static const char *program_name;
+static const char *vdso_name;
+static unsigned char elf_class;
+static unsigned int elf_abi;
+static bool need_swap;
+static FILE *out_file;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define HOST_ORDER            ELFDATA2LSB
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define HOST_ORDER            ELFDATA2MSB
+#endif
+
+#define BUILD_SWAP(bits)                                               \
+       static uint##bits##_t swap_uint##bits(uint##bits##_t val)       \
+       {                                                               \
+               return need_swap ? bswap_##bits(val) : val;             \
+       }
+
+BUILD_SWAP(16)
+BUILD_SWAP(32)
+BUILD_SWAP(64)
+
+#define __FUNC(name, bits) name##bits
+#define _FUNC(name, bits) __FUNC(name, bits)
+#define FUNC(name) _FUNC(name, ELF_BITS)
+
+#define __ELF(x, bits) Elf##bits##_##x
+#define _ELF(x, bits) __ELF(x, bits)
+#define ELF(x) _ELF(x, ELF_BITS)
+
+/*
+ * Include genvdso.h twice with ELF_BITS defined differently to get functions
+ * for both ELF32 and ELF64.
+ */
+
+#define ELF_BITS 64
+#include "genvdso.h"
+#undef ELF_BITS
+
+#define ELF_BITS 32
+#include "genvdso.h"
+#undef ELF_BITS
+
+static void *map_vdso(const char *path, size_t *_size)
+{
+       int fd;
+       struct stat stat;
+       void *addr;
+       const Elf32_Ehdr *ehdr;
+
+       fd = open(path, O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       if (fstat(fd, &stat) != 0) {
+               fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       addr = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+                   0);
+       if (addr == MAP_FAILED) {
+               fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name,
+                       path, strerror(errno));
+               return NULL;
+       }
+
+       /* ELF32/64 header formats are the same for the bits we're checking. */
+       ehdr = addr;
+
+       if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+               fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name,
+                       path);
+               return NULL;
+       }
+
+       elf_class = ehdr->e_ident[EI_CLASS];
+       switch (elf_class) {
+       case ELFCLASS32:
+       case ELFCLASS64:
+               break;
+       default:
+               fprintf(stderr, "%s: '%s' has invalid ELF class\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       switch (ehdr->e_ident[EI_DATA]) {
+       case ELFDATA2LSB:
+       case ELFDATA2MSB:
+               need_swap = ehdr->e_ident[EI_DATA] != HOST_ORDER;
+               break;
+       default:
+               fprintf(stderr, "%s: '%s' has invalid ELF data order\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       if (swap_uint16(ehdr->e_machine) != EM_MIPS) {
+               fprintf(stderr,
+                       "%s: '%s' has invalid ELF machine (expected EM_MIPS)\n",
+                       program_name, path);
+               return NULL;
+       } else if (swap_uint16(ehdr->e_type) != ET_DYN) {
+               fprintf(stderr,
+                       "%s: '%s' has invalid ELF type (expected ET_DYN)\n",
+                       program_name, path);
+               return NULL;
+       }
+
+       *_size = stat.st_size;
+       return addr;
+}
+
+static bool patch_vdso(const char *path, void *vdso)
+{
+       if (elf_class == ELFCLASS64)
+               return patch_vdso64(path, vdso);
+       else
+               return patch_vdso32(path, vdso);
+}
+
+static bool get_symbols(const char *path, void *vdso)
+{
+       if (elf_class == ELFCLASS64)
+               return get_symbols64(path, vdso);
+       else
+               return get_symbols32(path, vdso);
+}
+
+int main(int argc, char **argv)
+{
+       const char *dbg_vdso_path, *vdso_path, *out_path;
+       void *dbg_vdso, *vdso;
+       size_t dbg_vdso_size, vdso_size, i;
+
+       program_name = argv[0];
+
+       if (argc < 4 || argc > 5) {
+               fprintf(stderr,
+                       "Usage: %s <debug VDSO> <stripped VDSO> <output file> [<name>]\n",
+                       program_name);
+               return EXIT_FAILURE;
+       }
+
+       dbg_vdso_path = argv[1];
+       vdso_path = argv[2];
+       out_path = argv[3];
+       vdso_name = (argc > 4) ? argv[4] : "";
+
+       dbg_vdso = map_vdso(dbg_vdso_path, &dbg_vdso_size);
+       if (!dbg_vdso)
+               return EXIT_FAILURE;
+
+       vdso = map_vdso(vdso_path, &vdso_size);
+       if (!vdso)
+               return EXIT_FAILURE;
+
+       /* Patch both the VDSOs' ABI flags sections. */
+       if (!patch_vdso(dbg_vdso_path, dbg_vdso))
+               return EXIT_FAILURE;
+       if (!patch_vdso(vdso_path, vdso))
+               return EXIT_FAILURE;
+
+       if (msync(dbg_vdso, dbg_vdso_size, MS_SYNC) != 0) {
+               fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+                       dbg_vdso_path, strerror(errno));
+               return EXIT_FAILURE;
+       } else if (msync(vdso, vdso_size, MS_SYNC) != 0) {
+               fprintf(stderr, "%s: Failed to sync '%s': %s\n", program_name,
+                       vdso_path, strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       out_file = fopen(out_path, "w");
+       if (!out_file) {
+               fprintf(stderr, "%s: Failed to open '%s': %s\n", program_name,
+                       out_path, strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       fprintf(out_file, "/* Automatically generated - do not edit */\n");
+       fprintf(out_file, "#include <linux/linkage.h>\n");
+       fprintf(out_file, "#include <linux/mm.h>\n");
+       fprintf(out_file, "#include <asm/vdso.h>\n");
+
+       /* Write out the stripped VDSO data. */
+       fprintf(out_file,
+               "static unsigned char vdso_data[PAGE_ALIGN(%zu)] __page_aligned_data = {\n\t",
+               vdso_size);
+       for (i = 0; i < vdso_size; i++) {
+               if (!(i % 10))
+                       fprintf(out_file, "\n\t");
+               fprintf(out_file, "0x%02x, ", ((unsigned char *)vdso)[i]);
+       }
+       fprintf(out_file, "\n};\n");
+
+       /* Preallocate a page array. */
+       fprintf(out_file,
+               "static struct page *vdso_pages[PAGE_ALIGN(%zu) / PAGE_SIZE];\n",
+               vdso_size);
+
+       fprintf(out_file, "struct mips_vdso_image vdso_image%s%s = {\n",
+               (vdso_name[0]) ? "_" : "", vdso_name);
+       fprintf(out_file, "\t.data = vdso_data,\n");
+       fprintf(out_file, "\t.size = PAGE_ALIGN(%zu),\n", vdso_size);
+       fprintf(out_file, "\t.mapping = {\n");
+       fprintf(out_file, "\t\t.name = \"[vdso]\",\n");
+       fprintf(out_file, "\t\t.pages = vdso_pages,\n");
+       fprintf(out_file, "\t},\n");
+
+       /* Calculate and write symbol offsets to <output file> */
+       if (!get_symbols(dbg_vdso_path, dbg_vdso)) {
+               unlink(out_path);
+               return EXIT_FAILURE;
+       }
+
+       fprintf(out_file, "};\n");
+
+       return EXIT_SUCCESS;
+}
diff --git a/arch/mips/vdso/genvdso.h b/arch/mips/vdso/genvdso.h
new file mode 100644 (file)
index 0000000..9433472
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+static inline bool FUNC(patch_vdso)(const char *path, void *vdso)
+{
+       const ELF(Ehdr) *ehdr = vdso;
+       void *shdrs;
+       ELF(Shdr) *shdr;
+       char *shstrtab, *name;
+       uint16_t sh_count, sh_entsize, i;
+       unsigned int local_gotno, symtabno, gotsym;
+       ELF(Dyn) *dyn = NULL;
+
+       shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+       sh_count = swap_uint16(ehdr->e_shnum);
+       sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+       shdr = shdrs + (sh_entsize * swap_uint16(ehdr->e_shstrndx));
+       shstrtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+       for (i = 0; i < sh_count; i++) {
+               shdr = shdrs + (i * sh_entsize);
+               name = shstrtab + swap_uint32(shdr->sh_name);
+
+               /*
+                * Ensure there are no relocation sections - ld.so does not
+                * relocate the VDSO so if there are relocations things will
+                * break.
+                */
+               switch (swap_uint32(shdr->sh_type)) {
+               case SHT_REL:
+               case SHT_RELA:
+                       fprintf(stderr,
+                               "%s: '%s' contains relocation sections\n",
+                               program_name, path);
+                       return false;
+               case SHT_DYNAMIC:
+                       dyn = vdso + FUNC(swap_uint)(shdr->sh_offset);
+                       break;
+               }
+
+               /* Check for existing sections. */
+               if (strcmp(name, ".MIPS.abiflags") == 0) {
+                       fprintf(stderr,
+                               "%s: '%s' already contains a '.MIPS.abiflags' section\n",
+                               program_name, path);
+                       return false;
+               }
+
+               if (strcmp(name, ".mips_abiflags") == 0) {
+                       strcpy(name, ".MIPS.abiflags");
+                       shdr->sh_type = swap_uint32(SHT_MIPS_ABIFLAGS);
+                       shdr->sh_entsize = shdr->sh_size;
+               }
+       }
+
+       /*
+        * Ensure the GOT has no entries other than the standard 2, for the same
+        * reason we check that there's no relocation sections above.
+        * The standard two entries are:
+        * - Lazy resolver
+        * - Module pointer
+        */
+       if (dyn) {
+               local_gotno = symtabno = gotsym = 0;
+
+               while (FUNC(swap_uint)(dyn->d_tag) != DT_NULL) {
+                       switch (FUNC(swap_uint)(dyn->d_tag)) {
+                       /*
+                        * This member holds the number of local GOT entries.
+                        */
+                       case DT_MIPS_LOCAL_GOTNO:
+                               local_gotno = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       /*
+                        * This member holds the number of entries in the
+                        * .dynsym section.
+                        */
+                       case DT_MIPS_SYMTABNO:
+                               symtabno = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       /*
+                        * This member holds the index of the first dynamic
+                        * symbol table entry that corresponds to an entry in
+                        * the GOT.
+                        */
+                       case DT_MIPS_GOTSYM:
+                               gotsym = FUNC(swap_uint)(dyn->d_un.d_val);
+                               break;
+                       }
+
+                       dyn++;
+               }
+
+               if (local_gotno > 2 || symtabno - gotsym) {
+                       fprintf(stderr,
+                               "%s: '%s' contains unexpected GOT entries\n",
+                               program_name, path);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static inline bool FUNC(get_symbols)(const char *path, void *vdso)
+{
+       const ELF(Ehdr) *ehdr = vdso;
+       void *shdrs, *symtab;
+       ELF(Shdr) *shdr;
+       const ELF(Sym) *sym;
+       char *strtab, *name;
+       uint16_t sh_count, sh_entsize, st_count, st_entsize, i, j;
+       uint64_t offset;
+       uint32_t flags;
+
+       shdrs = vdso + FUNC(swap_uint)(ehdr->e_shoff);
+       sh_count = swap_uint16(ehdr->e_shnum);
+       sh_entsize = swap_uint16(ehdr->e_shentsize);
+
+       for (i = 0; i < sh_count; i++) {
+               shdr = shdrs + (i * sh_entsize);
+
+               if (swap_uint32(shdr->sh_type) == SHT_SYMTAB)
+                       break;
+       }
+
+       if (i == sh_count) {
+               fprintf(stderr, "%s: '%s' has no symbol table\n", program_name,
+                       path);
+               return false;
+       }
+
+       /* Get flags */
+       flags = swap_uint32(ehdr->e_flags);
+       if (elf_class == ELFCLASS64)
+               elf_abi = ABI_N64;
+       else if (flags & EF_MIPS_ABI2)
+               elf_abi = ABI_N32;
+       else
+               elf_abi = ABI_O32;
+
+       /* Get symbol table. */
+       symtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+       st_entsize = FUNC(swap_uint)(shdr->sh_entsize);
+       st_count = FUNC(swap_uint)(shdr->sh_size) / st_entsize;
+
+       /* Get string table. */
+       shdr = shdrs + (swap_uint32(shdr->sh_link) * sh_entsize);
+       strtab = vdso + FUNC(swap_uint)(shdr->sh_offset);
+
+       /* Write offsets for symbols needed by the kernel. */
+       for (i = 0; vdso_symbols[i].name; i++) {
+               if (!(vdso_symbols[i].abis & elf_abi))
+                       continue;
+
+               for (j = 0; j < st_count; j++) {
+                       sym = symtab + (j * st_entsize);
+                       name = strtab + swap_uint32(sym->st_name);
+
+                       if (!strcmp(name, vdso_symbols[i].name)) {
+                               offset = FUNC(swap_uint)(sym->st_value);
+
+                               fprintf(out_file,
+                                       "\t.%s = 0x%" PRIx64 ",\n",
+                                       vdso_symbols[i].offset_name, offset);
+                               break;
+                       }
+               }
+
+               if (j == st_count) {
+                       fprintf(stderr,
+                               "%s: '%s' is missing required symbol '%s'\n",
+                               program_name, path, vdso_symbols[i].name);
+                       return false;
+               }
+       }
+
+       return true;
+}
diff --git a/arch/mips/vdso/gettimeofday.c b/arch/mips/vdso/gettimeofday.c
new file mode 100644 (file)
index 0000000..ce89c9e
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/compiler.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/time.h>
+
+#include <asm/clocksource.h>
+#include <asm/io.h>
+#include <asm/mips-cm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+static __always_inline int do_realtime_coarse(struct timespec *ts,
+                                             const union mips_vdso_data *data)
+{
+       u32 start_seq;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               ts->tv_sec = data->xtime_sec;
+               ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       return 0;
+}
+
+static __always_inline int do_monotonic_coarse(struct timespec *ts,
+                                              const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u32 to_mono_sec;
+       u32 to_mono_nsec;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               ts->tv_sec = data->xtime_sec;
+               ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+
+               to_mono_sec = data->wall_to_mono_sec;
+               to_mono_nsec = data->wall_to_mono_nsec;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_sec += to_mono_sec;
+       timespec_add_ns(ts, to_mono_nsec);
+
+       return 0;
+}
+
+#ifdef CONFIG_CSRC_R4K
+
+static __always_inline u64 read_r4k_count(void)
+{
+       unsigned int count;
+
+       __asm__ __volatile__(
+       "       .set push\n"
+       "       .set mips32r2\n"
+       "       rdhwr   %0, $2\n"
+       "       .set pop\n"
+       : "=r" (count));
+
+       return count;
+}
+
+#endif
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static __always_inline u64 read_gic_count(const union mips_vdso_data *data)
+{
+       void __iomem *gic = get_gic(data);
+       u32 hi, hi2, lo;
+
+       do {
+               hi = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+               lo = __raw_readl(gic + GIC_UMV_SH_COUNTER_31_00_OFS);
+               hi2 = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+       } while (hi2 != hi);
+
+       return (((u64)hi) << 32) + lo;
+}
+
+#endif
+
+static __always_inline u64 get_ns(const union mips_vdso_data *data)
+{
+       u64 cycle_now, delta, nsec;
+
+       switch (data->clock_mode) {
+#ifdef CONFIG_CSRC_R4K
+       case VDSO_CLOCK_R4K:
+               cycle_now = read_r4k_count();
+               break;
+#endif
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+       case VDSO_CLOCK_GIC:
+               cycle_now = read_gic_count(data);
+               break;
+#endif
+       default:
+               return 0;
+       }
+
+       delta = (cycle_now - data->cs_cycle_last) & data->cs_mask;
+
+       nsec = (delta * data->cs_mult) + data->xtime_nsec;
+       nsec >>= data->cs_shift;
+
+       return nsec;
+}
+
+static __always_inline int do_realtime(struct timespec *ts,
+                                      const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u64 ns;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               if (data->clock_mode == VDSO_CLOCK_NONE)
+                       return -ENOSYS;
+
+               ts->tv_sec = data->xtime_sec;
+               ns = get_ns(data);
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, ns);
+
+       return 0;
+}
+
+static __always_inline int do_monotonic(struct timespec *ts,
+                                       const union mips_vdso_data *data)
+{
+       u32 start_seq;
+       u64 ns;
+       u32 to_mono_sec;
+       u32 to_mono_nsec;
+
+       do {
+               start_seq = vdso_data_read_begin(data);
+
+               if (data->clock_mode == VDSO_CLOCK_NONE)
+                       return -ENOSYS;
+
+               ts->tv_sec = data->xtime_sec;
+               ns = get_ns(data);
+
+               to_mono_sec = data->wall_to_mono_sec;
+               to_mono_nsec = data->wall_to_mono_nsec;
+       } while (vdso_data_read_retry(data, start_seq));
+
+       ts->tv_sec += to_mono_sec;
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, ns + to_mono_nsec);
+
+       return 0;
+}
+
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+       const union mips_vdso_data *data = get_vdso_data();
+       struct timespec ts;
+       int ret;
+
+       ret = do_realtime(&ts, data);
+       if (ret)
+               return ret;
+
+       if (tv) {
+               tv->tv_sec = ts.tv_sec;
+               tv->tv_usec = ts.tv_nsec / 1000;
+       }
+
+       if (tz) {
+               tz->tz_minuteswest = data->tz_minuteswest;
+               tz->tz_dsttime = data->tz_dsttime;
+       }
+
+       return 0;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+       const union mips_vdso_data *data = get_vdso_data();
+       int ret;
+
+       switch (clkid) {
+       case CLOCK_REALTIME_COARSE:
+               ret = do_realtime_coarse(ts, data);
+               break;
+       case CLOCK_MONOTONIC_COARSE:
+               ret = do_monotonic_coarse(ts, data);
+               break;
+       case CLOCK_REALTIME:
+               ret = do_realtime(ts, data);
+               break;
+       case CLOCK_MONOTONIC:
+               ret = do_monotonic(ts, data);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       /* If we return -ENOSYS libc should fall back to a syscall. */
+       return ret;
+}
diff --git a/arch/mips/vdso/sigreturn.S b/arch/mips/vdso/sigreturn.S
new file mode 100644 (file)
index 0000000..715bf59
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <uapi/asm/unistd.h>
+
+#include <asm/regdef.h>
+#include <asm/asm.h>
+
+       .section        .text
+       .cfi_sections   .debug_frame
+
+LEAF(__vdso_rt_sigreturn)
+       .cfi_startproc
+       .frame  sp, 0, ra
+       .mask   0x00000000, 0
+       .fmask  0x00000000, 0
+       .cfi_signal_frame
+
+       li      v0, __NR_rt_sigreturn
+       syscall
+
+       .cfi_endproc
+       END(__vdso_rt_sigreturn)
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+LEAF(__vdso_sigreturn)
+       .cfi_startproc
+       .frame  sp, 0, ra
+       .mask   0x00000000, 0
+       .fmask  0x00000000, 0
+       .cfi_signal_frame
+
+       li      v0, __NR_sigreturn
+       syscall
+
+       .cfi_endproc
+       END(__vdso_sigreturn)
+
+#endif
diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h
new file mode 100644 (file)
index 0000000..cfb1be4
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
+
+/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
+#undef CONFIG_64BIT
+#define CONFIG_32BIT 1
+#ifndef __ASSEMBLY__
+#include <asm-generic/atomic64.h>
+#endif
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <asm/asm.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+static inline unsigned long get_vdso_base(void)
+{
+       unsigned long addr;
+
+       /*
+        * We can't use cpu_has_mips_r6 since it needs the cpu_data[]
+        * kernel symbol.
+        */
+#ifdef CONFIG_CPU_MIPSR6
+       /*
+        * lapc <symbol> is an alias to addiupc reg, <symbol> - .
+        *
+        * We can't use addiupc because there is no label-label
+        * support for the addiupc reloc
+        */
+       __asm__("lapc   %0, _start                      \n"
+               : "=r" (addr) : :);
+#else
+       /*
+        * Get the base load address of the VDSO. We have to avoid generating
+        * relocations and references to the GOT because ld.so does not peform
+        * relocations on the VDSO. We use the current offset from the VDSO base
+        * and perform a PC-relative branch which gives the absolute address in
+        * ra, and take the difference. The assembler chokes on
+        * "li %0, _start - .", so embed the offset as a word and branch over
+        * it.
+        *
+        */
+
+       __asm__(
+       "       .set push                               \n"
+       "       .set noreorder                          \n"
+       "       bal     1f                              \n"
+       "        nop                                    \n"
+       "       .word   _start - .                      \n"
+       "1:     lw      %0, 0($31)                      \n"
+       "       " STR(PTR_ADDU) " %0, $31, %0           \n"
+       "       .set pop                                \n"
+       : "=r" (addr)
+       :
+       : "$31");
+#endif /* CONFIG_CPU_MIPSR6 */
+
+       return addr;
+}
+
+static inline const union mips_vdso_data *get_vdso_data(void)
+{
+       return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE);
+}
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static inline void __iomem *get_gic(const union mips_vdso_data *data)
+{
+       return (void __iomem *)data - PAGE_SIZE;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S
new file mode 100644 (file)
index 0000000..8df7dd5
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/sgidefs.h>
+
+#if _MIPS_SIM == _MIPS_SIM_ABI64
+OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips")
+#elif _MIPS_SIM == _MIPS_SIM_NABI32
+OUTPUT_FORMAT("elf32-ntradlittlemips", "elf32-ntradbigmips", "elf32-ntradlittlemips")
+#else
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips", "elf32-tradlittlemips")
+#endif
+
+OUTPUT_ARCH(mips)
+
+SECTIONS
+{
+       PROVIDE(_start = .);
+       . = SIZEOF_HEADERS;
+
+       /*
+        * In order to retain compatibility with older toolchains we provide the
+        * ABI flags section ourself. Newer assemblers will automatically
+        * generate .MIPS.abiflags sections so we discard such input sections,
+        * and then manually define our own section here. genvdso will patch
+        * this section to have the correct name/type.
+        */
+       .mips_abiflags  : { *(.mips_abiflags) }         :text :abiflags
+
+       .reginfo        : { *(.reginfo) }               :text :reginfo
+
+       .hash           : { *(.hash) }                  :text
+       .gnu.hash       : { *(.gnu.hash) }
+       .dynsym         : { *(.dynsym) }
+       .dynstr         : { *(.dynstr) }
+       .gnu.version    : { *(.gnu.version) }
+       .gnu.version_d  : { *(.gnu.version_d) }
+       .gnu.version_r  : { *(.gnu.version_r) }
+
+       .note           : { *(.note.*) }                :text :note
+
+       .text           : { *(.text*) }                 :text
+       PROVIDE (__etext = .);
+       PROVIDE (_etext = .);
+       PROVIDE (etext = .);
+
+       .eh_frame_hdr   : { *(.eh_frame_hdr) }          :text :eh_frame_hdr
+       .eh_frame       : { KEEP (*(.eh_frame)) }       :text
+
+       .dynamic        : { *(.dynamic) }               :text :dynamic
+
+       .rodata         : { *(.rodata*) }               :text
+
+       _end = .;
+       PROVIDE(end = .);
+
+       /DISCARD/       : {
+               *(.MIPS.abiflags)
+               *(.gnu.attributes)
+               *(.note.GNU-stack)
+               *(.data .data.* .gnu.linkonce.d.* .sdata*)
+               *(.bss .sbss .dynbss .dynsbss)
+       }
+}
+
+PHDRS
+{
+       /*
+        * Provide a PT_MIPS_ABIFLAGS header to assign the ABI flags section
+        * to. We can specify the header type directly here so no modification
+        * is needed later on.
+        */
+       abiflags        0x70000003;
+
+       /*
+        * The ABI flags header must exist directly after the PT_INTERP header,
+        * so we must explicitly place the PT_MIPS_REGINFO header after it to
+        * stop the linker putting one in at the start.
+        */
+       reginfo         0x70000000;
+
+       text            PT_LOAD         FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+       dynamic         PT_DYNAMIC      FLAGS(4);               /* PF_R */
+       note            PT_NOTE         FLAGS(4);               /* PF_R */
+       eh_frame_hdr    PT_GNU_EH_FRAME;
+}
+
+VERSION
+{
+       LINUX_2.6 {
+#ifndef DISABLE_MIPS_VDSO
+       global:
+               __vdso_clock_gettime;
+               __vdso_gettimeofday;
+#endif
+       local: *;
+       };
+}
diff --git a/arch/mips/xilfpga/Kconfig b/arch/mips/xilfpga/Kconfig
new file mode 100644 (file)
index 0000000..42a030a
--- /dev/null
@@ -0,0 +1,9 @@
+choice
+       prompt "Machine type"
+       depends on MACH_XILFPGA
+       default XILFPGA_NEXYS4DDR
+
+config XILFPGA_NEXYS4DDR
+       bool "Nexys4DDR by Digilent"
+
+endchoice
diff --git a/arch/mips/xilfpga/Makefile b/arch/mips/xilfpga/Makefile
new file mode 100644 (file)
index 0000000..a4deec6
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Xilfpga
+#
+
+obj-y +=       init.o
+obj-y +=       intc.o
+obj-y +=       time.o
diff --git a/arch/mips/xilfpga/Platform b/arch/mips/xilfpga/Platform
new file mode 100644 (file)
index 0000000..ed375af
--- /dev/null
@@ -0,0 +1,3 @@
+platform-$(CONFIG_MACH_XILFPGA) += xilfpga/
+cflags-$(CONFIG_MACH_XILFPGA) += -I$(srctree)/arch/mips/include/asm/mach-xilfpga
+load-$(CONFIG_MACH_XILFPGA) += 0xffffffff80100000
diff --git a/arch/mips/xilfpga/init.c b/arch/mips/xilfpga/init.c
new file mode 100644 (file)
index 0000000..ce2aee2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Xilfpga platform setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/prom.h>
+
+#define XILFPGA_UART_BASE      0xb0401000
+
+const char *get_system_type(void)
+{
+       return "MIPSfpga";
+}
+
+void __init plat_mem_setup(void)
+{
+       __dt_setup_arch(__dtb_start);
+       strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+}
+
+void __init prom_init(void)
+{
+       setup_8250_early_printk_port(XILFPGA_UART_BASE, 2, 50000);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init device_tree_init(void)
+{
+       if (!initial_boot_params)
+               return;
+
+       unflatten_and_copy_device_tree();
+}
+
+static int __init plat_of_setup(void)
+{
+       if (!of_have_populated_dt())
+               panic("Device tree not present");
+
+       if (of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL))
+               panic("Failed to populate DT");
+
+       return 0;
+}
+arch_initcall(plat_of_setup);
diff --git a/arch/mips/xilfpga/intc.c b/arch/mips/xilfpga/intc.c
new file mode 100644 (file)
index 0000000..c4d1a71
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Xilfpga interrupt controller setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <asm/irq_cpu.h>
+
+static struct of_device_id of_irq_ids[] __initdata = {
+       { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+       {},
+};
+
+void __init arch_init_irq(void)
+{
+       of_irq_init(of_irq_ids);
+}
diff --git a/arch/mips/xilfpga/time.c b/arch/mips/xilfpga/time.c
new file mode 100644 (file)
index 0000000..cbb3fca
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Xilfpga clocksource/timer setup
+ *
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/of.h>
+
+#include <asm/time.h>
+
+void __init plat_time_init(void)
+{
+       struct device_node *np;
+       struct clk *clk;
+
+       of_clk_init(NULL);
+       clocksource_probe();
+
+       np = of_get_cpu_node(0, NULL);
+       if (!np) {
+               pr_err("Failed to get CPU node\n");
+               return;
+       }
+
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+               return;
+       }
+
+       mips_hpt_frequency = clk_get_rate(clk) / 2;
+       clk_put(clk);
+}
index 223cdcc8203f566483c15051c1ce5cfdfe608791..87bf88ed04c6c0a13220e2b3588b7fedbb6145f3 100644 (file)
@@ -23,22 +23,6 @@ static void __flush_dcache(unsigned long start, unsigned long end)
        end += (cpuinfo.dcache_line_size - 1);
        end &= ~(cpuinfo.dcache_line_size - 1);
 
-       for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {
-               __asm__ __volatile__ ("   flushda 0(%0)\n"
-                                       : /* Outputs */
-                                       : /* Inputs  */ "r"(addr)
-                                       /* : No clobber */);
-       }
-}
-
-static void __flush_dcache_all(unsigned long start, unsigned long end)
-{
-       unsigned long addr;
-
-       start &= ~(cpuinfo.dcache_line_size - 1);
-       end += (cpuinfo.dcache_line_size - 1);
-       end &= ~(cpuinfo.dcache_line_size - 1);
-
        if (end > start + cpuinfo.dcache_size)
                end = start + cpuinfo.dcache_size;
 
@@ -112,7 +96,7 @@ static void flush_aliases(struct address_space *mapping, struct page *page)
 
 void flush_cache_all(void)
 {
-       __flush_dcache_all(0, cpuinfo.dcache_size);
+       __flush_dcache(0, cpuinfo.dcache_size);
        __flush_icache(0, cpuinfo.icache_size);
 }
 
@@ -182,7 +166,7 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
         */
        unsigned long start = (unsigned long)page_address(page);
 
-       __flush_dcache_all(start, start + PAGE_SIZE);
+       __flush_dcache(start, start + PAGE_SIZE);
 }
 
 void flush_dcache_page(struct page *page)
@@ -268,7 +252,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
 {
        flush_cache_page(vma, user_vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       __flush_dcache_all((unsigned long)src, (unsigned long)src + len);
+       __flush_dcache((unsigned long)src, (unsigned long)src + len);
        if (vma->vm_flags & VM_EXEC)
                __flush_icache((unsigned long)src, (unsigned long)src + len);
 }
@@ -279,7 +263,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
 {
        flush_cache_page(vma, user_vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       __flush_dcache_all((unsigned long)dst, (unsigned long)dst + len);
+       __flush_dcache((unsigned long)dst, (unsigned long)dst + len);
        if (vma->vm_flags & VM_EXEC)
                __flush_icache((unsigned long)dst, (unsigned long)dst + len);
 }
index c36546959e86ff96f4b0a656d1562ee85e729904..729f89163bc32113dba77e309c8ce767ed3d15e8 100644 (file)
@@ -108,6 +108,9 @@ config PGTABLE_LEVELS
        default 3 if 64BIT && PARISC_PAGE_SIZE_4KB
        default 2
 
+config SYS_SUPPORTS_HUGETLBFS
+       def_bool y if PA20
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h
new file mode 100644 (file)
index 0000000..7d56a9c
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef _ASM_PARISC64_HUGETLB_H
+#define _ASM_PARISC64_HUGETLB_H
+
+#include <asm/page.h>
+#include <asm-generic/hugetlb.h>
+
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t pte);
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep);
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+                                        unsigned long addr,
+                                        unsigned long len) {
+       return 0;
+}
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(struct file *file,
+                       unsigned long addr, unsigned long len)
+{
+       if (len & ~HPAGE_MASK)
+               return -EINVAL;
+       if (addr & ~HPAGE_MASK)
+               return -EINVAL;
+       return 0;
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
+                                         unsigned long addr, unsigned long end,
+                                         unsigned long floor,
+                                         unsigned long ceiling)
+{
+       free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+                                        unsigned long addr, pte_t *ptep)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+       return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+       return pte_wrprotect(pte);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+                                          unsigned long addr, pte_t *ptep)
+{
+       pte_t old_pte = *ptep;
+       set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+                                            unsigned long addr, pte_t *ptep,
+                                            pte_t pte, int dirty)
+{
+       int changed = !pte_same(*ptep, pte);
+       if (changed) {
+               set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+               flush_tlb_page(vma, addr);
+       }
+       return changed;
+}
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+       return *ptep;
+}
+
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
+#endif /* _ASM_PARISC64_HUGETLB_H */
index 60d5d174dfe413e14cb5117a04536ce7948d937d..80e742a1c162fbd89b27a21bd4ff75eb169b9b38 100644 (file)
@@ -145,11 +145,22 @@ extern int npmem_ranges;
 #endif /* CONFIG_DISCONTIGMEM */
 
 #ifdef CONFIG_HUGETLB_PAGE
-#define HPAGE_SHIFT            22      /* 4MB (is this fixed?) */
+#define HPAGE_SHIFT            PMD_SHIFT /* fixed for transparent huge pages */
 #define HPAGE_SIZE             ((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+
+#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define REAL_HPAGE_SHIFT      20 /* 20 = 1MB */
+# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_1M
+#elif !defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
+# define REAL_HPAGE_SHIFT      22 /* 22 = 4MB */
+# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4M
+#else
+# define REAL_HPAGE_SHIFT      24 /* 24 = 16MB */
+# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16M
 #endif
+#endif /* CONFIG_HUGETLB_PAGE */
 
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
index 3edbb9fc91b4e055307d3c7519592a00201d988a..f2fd327dce2edc14db5717211fe27943e957fcf0 100644 (file)
@@ -35,7 +35,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
                                        PxD_FLAG_VALID | 
                                        PxD_FLAG_ATTACHED) 
                        + (__u32)(__pa((unsigned long)pgd) >> PxD_VALUE_SHIFT));
-               /* The first pmd entry also is marked with _PAGE_GATEWAY as
+               /* The first pmd entry also is marked with PxD_FLAG_ATTACHED as
                 * a signal that this pmd may not be freed */
                __pgd_val_set(*pgd, PxD_FLAG_ATTACHED);
 #endif
index f93c4a4e6580300f347a4d69beccc5fe4810452b..d8534f95915a3754c233fd14466aef6cbfba40dc 100644 (file)
@@ -83,7 +83,11 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
        printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e))
 
 /* This is the size of the initially mapped kernel memory */
-#define KERNEL_INITIAL_ORDER   24      /* 0 to 1<<24 = 16MB */
+#ifdef CONFIG_64BIT
+#define KERNEL_INITIAL_ORDER   25      /* 1<<25 = 32MB */
+#else
+#define KERNEL_INITIAL_ORDER   24      /* 1<<24 = 16MB */
+#endif
 #define KERNEL_INITIAL_SIZE    (1 << KERNEL_INITIAL_ORDER)
 
 #if CONFIG_PGTABLE_LEVELS == 3
@@ -167,7 +171,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 #define _PAGE_NO_CACHE_BIT 24   /* (0x080) Uncached Page (U bit) */
 #define _PAGE_ACCESSED_BIT 23   /* (0x100) Software: Page Accessed */
 #define _PAGE_PRESENT_BIT  22   /* (0x200) Software: translation valid */
-/* bit 21 was formerly the FLUSH bit but is now unused */
+#define _PAGE_HPAGE_BIT    21   /* (0x400) Software: Huge Page */
 #define _PAGE_USER_BIT     20   /* (0x800) Software: User accessible page */
 
 /* N.B. The bits are defined in terms of a 32 bit word above, so the */
@@ -194,6 +198,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
 #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
 #define _PAGE_PRESENT  (1 << xlate_pabit(_PAGE_PRESENT_BIT))
+#define _PAGE_HUGE     (1 << xlate_pabit(_PAGE_HPAGE_BIT))
 #define _PAGE_USER     (1 << xlate_pabit(_PAGE_USER_BIT))
 
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE |  _PAGE_DIRTY | _PAGE_ACCESSED)
@@ -217,7 +222,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 #define PxD_FLAG_VALID    (1 << xlate_pabit(_PxD_VALID_BIT))
 #define PxD_FLAG_MASK     (0xf)
 #define PxD_FLAG_SHIFT    (4)
-#define PxD_VALUE_SHIFT   (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
+#define PxD_VALUE_SHIFT   (PFN_PTE_SHIFT-PxD_FLAG_SHIFT)
 
 #ifndef __ASSEMBLY__
 
@@ -362,6 +367,18 @@ static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; ret
 static inline pte_t pte_mkwrite(pte_t pte)     { pte_val(pte) |= _PAGE_WRITE; return pte; }
 static inline pte_t pte_mkspecial(pte_t pte)   { return pte; }
 
+/*
+ * Huge pte definitions.
+ */
+#ifdef CONFIG_HUGETLB_PAGE
+#define pte_huge(pte)           (pte_val(pte) & _PAGE_HUGE)
+#define pte_mkhuge(pte)         (__pte(pte_val(pte) | _PAGE_HUGE))
+#else
+#define pte_huge(pte)           (0)
+#define pte_mkhuge(pte)         (pte)
+#endif
+
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -410,8 +427,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 /* Find an entry in the second-level page table.. */
 
 #if CONFIG_PGTABLE_LEVELS == 3
+#define pmd_index(addr)         (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
 #define pmd_offset(dir,address) \
-((pmd_t *) pgd_page_vaddr(*(dir)) + (((address)>>PMD_SHIFT) & (PTRS_PER_PMD-1)))
+((pmd_t *) pgd_page_vaddr(*(dir)) + pmd_index(address))
 #else
 #define pmd_offset(dir,addr) ((pmd_t *) dir)
 #endif
index 54adb60c0a42cca573abc1ca091328c9e6ca8b58..7e759ecb1343692a11a16526aaff04c5eb607cec 100644 (file)
@@ -192,33 +192,6 @@ void show_trace(struct task_struct *task, unsigned long *stack);
  */
 typedef unsigned int elf_caddr_t;
 
-#define start_thread_som(regs, new_pc, new_sp) do {    \
-       unsigned long *sp = (unsigned long *)new_sp;    \
-       __u32 spaceid = (__u32)current->mm->context;    \
-       unsigned long pc = (unsigned long)new_pc;       \
-       /* offset pc for priv. level */                 \
-       pc |= 3;                                        \
-                                                       \
-       regs->iasq[0] = spaceid;                        \
-       regs->iasq[1] = spaceid;                        \
-       regs->iaoq[0] = pc;                             \
-       regs->iaoq[1] = pc + 4;                         \
-       regs->sr[2] = LINUX_GATEWAY_SPACE;              \
-       regs->sr[3] = 0xffff;                           \
-       regs->sr[4] = spaceid;                          \
-       regs->sr[5] = spaceid;                          \
-       regs->sr[6] = spaceid;                          \
-       regs->sr[7] = spaceid;                          \
-       regs->gr[ 0] = USER_PSW;                        \
-       regs->gr[30] = ((new_sp)+63)&~63;               \
-       regs->gr[31] = pc;                              \
-                                                       \
-       get_user(regs->gr[26],&sp[0]);                  \
-       get_user(regs->gr[25],&sp[-1]);                 \
-       get_user(regs->gr[24],&sp[-2]);                 \
-       get_user(regs->gr[23],&sp[-3]);                 \
-} while(0)
-
 /* The ELF abi wants things done a "wee bit" differently than
  * som does.  Supporting this behavior here avoids
  * having our own version of create_elf_tables.
index ecc3ae1ca28e2d573f578709fa6c2c023159fa72..dd4d1876a020c1e0150cc87547e3f75f9940f16b 100644 (file)
 #define MADV_DONTFORK  10              /* don't inherit across fork */
 #define MADV_DOFORK    11              /* do inherit across fork */
 
-/* The range 12-64 is reserved for page size specification. */
-#define MADV_4K_PAGES   12              /* Use 4K pages  */
-#define MADV_16K_PAGES  14              /* Use 16K pages */
-#define MADV_64K_PAGES  16              /* Use 64K pages */
-#define MADV_256K_PAGES 18              /* Use 256K pages */
-#define MADV_1M_PAGES   20              /* Use 1 Megabyte pages */
-#define MADV_4M_PAGES   22              /* Use 4 Megabyte pages */
-#define MADV_16M_PAGES  24              /* Use 16 Megabyte pages */
-#define MADV_64M_PAGES  26              /* Use 64 Megabyte pages */
-
 #define MADV_MERGEABLE   65            /* KSM may merge identical pages */
 #define MADV_UNMERGEABLE 66            /* KSM may not merge identical pages */
 
index 59001cea13f9bea05c1071cc6aaaf1fad9ad3458..d2f62570a7b16d4f4c6321515d980f048cd278f2 100644 (file)
@@ -289,6 +289,14 @@ int main(void)
        DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE);
        DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT);
        DEFINE(ASM_PT_INITIAL, PT_INITIAL);
+       BLANK();
+       /* HUGEPAGE_SIZE is only used in vmlinux.lds.S to align kernel text
+        * and kernel data on physical huge pages */
+#ifdef CONFIG_HUGETLB_PAGE
+       DEFINE(HUGEPAGE_SIZE, 1UL << REAL_HPAGE_SHIFT);
+#else
+       DEFINE(HUGEPAGE_SIZE, PAGE_SIZE);
+#endif
        BLANK();
        DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
        DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
index c5ef4081b01d2f0aee841a7f8f06b0be416a6fd8..623496c117564cdbc7f939dea4ff777e114212ac 100644 (file)
        STREG           \pte,0(\ptp)
        .endm
 
+       /* We have (depending on the page size):
+        * - 38 to 52-bit Physical Page Number
+        * - 12 to 26-bit page offset
+        */
        /* bitshift difference between a PFN (based on kernel's PAGE_SIZE)
         * to a CPU TLB 4k PFN (4k => 12 bits to shift) */
-       #define PAGE_ADD_SHIFT  (PAGE_SHIFT-12)
+       #define PAGE_ADD_SHIFT          (PAGE_SHIFT-12)
+       #define PAGE_ADD_HUGE_SHIFT     (REAL_HPAGE_SHIFT-12)
 
        /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
-       .macro          convert_for_tlb_insert20 pte
+       .macro          convert_for_tlb_insert20 pte,tmp
+#ifdef CONFIG_HUGETLB_PAGE
+       copy            \pte,\tmp
+       extrd,u         \tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
+                               64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
+
+       depdi           _PAGE_SIZE_ENCODING_DEFAULT,63,\
+                               (63-58)+PAGE_ADD_SHIFT,\pte
+       extrd,u,*=      \tmp,_PAGE_HPAGE_BIT+32,1,%r0
+       depdi           _HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
+                               (63-58)+PAGE_ADD_HUGE_SHIFT,\pte
+#else /* Huge pages disabled */
        extrd,u         \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
                                64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
        depdi           _PAGE_SIZE_ENCODING_DEFAULT,63,\
                                (63-58)+PAGE_ADD_SHIFT,\pte
+#endif
        .endm
 
        /* Convert the pte and prot to tlb insertion values.  How
         * this happens is quite subtle, read below */
-       .macro          make_insert_tlb spc,pte,prot
+       .macro          make_insert_tlb spc,pte,prot,tmp
        space_to_prot   \spc \prot        /* create prot id from space */
        /* The following is the real subtlety.  This is depositing
         * T <-> _PAGE_REFTRAP
        depdi           1,12,1,\prot
 
        /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
-       convert_for_tlb_insert20 \pte
+       convert_for_tlb_insert20 \pte \tmp
        .endm
 
        /* Identical macro to make_insert_tlb above, except it
 
 
        /*
-        * Align fault_vector_20 on 4K boundary so that both
-        * fault_vector_11 and fault_vector_20 are on the
-        * same page. This is only necessary as long as we
-        * write protect the kernel text, which we may stop
-        * doing once we use large page translations to cover
-        * the static part of the kernel address space.
+        * Fault_vectors are architecturally required to be aligned on a 2K
+        * boundary
         */
 
        .text
-
-       .align 4096
+       .align 2048
 
 ENTRY(fault_vector_20)
        /* First vector is invalid (0) */
@@ -1147,7 +1159,7 @@ dtlb_miss_20w:
        tlb_lock        spc,ptp,pte,t0,t1,dtlb_check_alias_20w
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
        
        idtlbt          pte,prot
 
@@ -1173,7 +1185,7 @@ nadtlb_miss_20w:
        tlb_lock        spc,ptp,pte,t0,t1,nadtlb_check_alias_20w
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        idtlbt          pte,prot
 
@@ -1267,7 +1279,7 @@ dtlb_miss_20:
        tlb_lock        spc,ptp,pte,t0,t1,dtlb_check_alias_20
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        f_extend        pte,t1
 
@@ -1295,7 +1307,7 @@ nadtlb_miss_20:
        tlb_lock        spc,ptp,pte,t0,t1,nadtlb_check_alias_20
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        f_extend        pte,t1
        
@@ -1404,7 +1416,7 @@ itlb_miss_20w:
        tlb_lock        spc,ptp,pte,t0,t1,itlb_fault
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
        
        iitlbt          pte,prot
 
@@ -1428,7 +1440,7 @@ naitlb_miss_20w:
        tlb_lock        spc,ptp,pte,t0,t1,naitlb_check_alias_20w
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        iitlbt          pte,prot
 
@@ -1514,7 +1526,7 @@ itlb_miss_20:
        tlb_lock        spc,ptp,pte,t0,t1,itlb_fault
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        f_extend        pte,t1
 
@@ -1534,7 +1546,7 @@ naitlb_miss_20:
        tlb_lock        spc,ptp,pte,t0,t1,naitlb_check_alias_20
        update_accessed ptp,pte,t0,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        f_extend        pte,t1
 
@@ -1566,7 +1578,7 @@ dbit_trap_20w:
        tlb_lock        spc,ptp,pte,t0,t1,dbit_fault
        update_dirty    ptp,pte,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
                
        idtlbt          pte,prot
 
@@ -1610,7 +1622,7 @@ dbit_trap_20:
        tlb_lock        spc,ptp,pte,t0,t1,dbit_fault
        update_dirty    ptp,pte,t1
 
-       make_insert_tlb spc,pte,prot
+       make_insert_tlb spc,pte,prot,t1
 
        f_extend        pte,t1
        
index e7d64527aff94f69b019f7bde3aad63da47420ec..75aa0db9f69efe2fb3fa00d10d6fc66bd3f2b923 100644 (file)
@@ -69,7 +69,7 @@ $bss_loop:
        stw,ma          %arg2,4(%r1)
        stw,ma          %arg3,4(%r1)
 
-       /* Initialize startup VM. Just map first 8/16 MB of memory */
+       /* Initialize startup VM. Just map first 16/32 MB of memory */
        load32          PA(swapper_pg_dir),%r4
        mtctl           %r4,%cr24       /* Initialize kernel root pointer */
        mtctl           %r4,%cr25       /* Initialize user root pointer */
@@ -107,7 +107,7 @@ $bss_loop:
        /* Now initialize the PTEs themselves.  We use RWX for
         * everything ... it will get remapped correctly later */
        ldo             0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */
-       ldi             (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
+       load32          (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
        load32          PA(pg0),%r1
 
 $pgt_fill_loop:
index 72a3c658ad7bdbc3a0429f4c85f1d890b914e38c..f7ea626e29c9b3bce80d28062cbf802ab2313785 100644 (file)
@@ -130,7 +130,16 @@ void __init setup_arch(char **cmdline_p)
        printk(KERN_INFO "The 32-bit Kernel has started...\n");
 #endif
 
-       printk(KERN_INFO "Default page size is %dKB.\n", (int)(PAGE_SIZE / 1024));
+       printk(KERN_INFO "Kernel default page size is %d KB. Huge pages ",
+               (int)(PAGE_SIZE / 1024));
+#ifdef CONFIG_HUGETLB_PAGE
+       printk(KERN_CONT "enabled with %d MB physical and %d MB virtual size",
+                1 << (REAL_HPAGE_SHIFT - 20), 1 << (HPAGE_SHIFT - 20));
+#else
+       printk(KERN_CONT "disabled");
+#endif
+       printk(KERN_CONT ".\n");
+
 
        pdc_console_init();
 
@@ -377,6 +386,7 @@ arch_initcall(parisc_init);
 void start_parisc(void)
 {
        extern void start_kernel(void);
+       extern void early_trap_init(void);
 
        int ret, cpunum;
        struct pdc_coproc_cfg coproc_cfg;
@@ -397,6 +407,8 @@ void start_parisc(void)
                panic("must have an fpu to boot linux");
        }
 
+       early_trap_init(); /* initialize checksum of fault_vector */
+
        start_kernel();
        // not reached
 }
index 0b8d26d3ba43be545308dc70075a4a224a8b8155..3fbd7252a4b27efd106250f5b21e98910f8af8bd 100644 (file)
@@ -369,7 +369,7 @@ tracesys_exit:
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
        ldo     TASK_REGS(%r1),%r26
-       bl      do_syscall_trace_exit,%r2
+       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
@@ -390,7 +390,7 @@ tracesys_sigexit:
 #ifdef CONFIG_64BIT
        ldo     -16(%r30),%r29                  /* Reference param save area */
 #endif
-       bl      do_syscall_trace_exit,%r2
+       BL      do_syscall_trace_exit,%r2
        ldo     TASK_REGS(%r1),%r26
 
        ldil    L%syscall_exit_rfi,%r1
index b99b39f1da02431865b94e6bfe720e9858163a0d..553b09855cfd8799acde0df3d9118afcfcf5cbb0 100644 (file)
@@ -807,7 +807,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 }
 
 
-int __init check_ivt(void *iva)
+void __init initialize_ivt(const void *iva)
 {
        extern u32 os_hpmc_size;
        extern const u32 os_hpmc[];
@@ -818,8 +818,8 @@ int __init check_ivt(void *iva)
        u32 *hpmcp;
        u32 length;
 
-       if (strcmp((char *)iva, "cows can fly"))
-               return -1;
+       if (strcmp((const char *)iva, "cows can fly"))
+               panic("IVT invalid");
 
        ivap = (u32 *)iva;
 
@@ -839,28 +839,23 @@ int __init check_ivt(void *iva)
            check += ivap[i];
 
        ivap[5] = -check;
-
-       return 0;
 }
        
-#ifndef CONFIG_64BIT
-extern const void fault_vector_11;
-#endif
-extern const void fault_vector_20;
 
-void __init trap_init(void)
+/* early_trap_init() is called before we set up kernel mappings and
+ * write-protect the kernel */
+void  __init early_trap_init(void)
 {
-       void *iva;
+       extern const void fault_vector_20;
 
-       if (boot_cpu_data.cpu_type >= pcxu)
-               iva = (void *) &fault_vector_20;
-       else
-#ifdef CONFIG_64BIT
-               panic("Can't boot 64-bit OS on PA1.1 processor!");
-#else
-               iva = (void *) &fault_vector_11;
+#ifndef CONFIG_64BIT
+       extern const void fault_vector_11;
+       initialize_ivt(&fault_vector_11);
 #endif
 
-       if (check_ivt(iva))
-               panic("IVT invalid");
+       initialize_ivt(&fault_vector_20);
+}
+
+void __init trap_init(void)
+{
 }
index 0dacc5ca555afe7643da970bf9f3ae75ebc88790..308f29081d461b0a9b0a0d8eec0d54e0a1936ff3 100644 (file)
@@ -60,7 +60,7 @@ SECTIONS
                EXIT_DATA
        }
        PERCPU_SECTION(8)
-       . = ALIGN(PAGE_SIZE);
+       . = ALIGN(HUGEPAGE_SIZE);
        __init_end = .;
        /* freed after init ends here */
 
@@ -116,7 +116,7 @@ SECTIONS
         * that we can properly leave these
         * as writable
         */
-       . = ALIGN(PAGE_SIZE);
+       . = ALIGN(HUGEPAGE_SIZE);
        data_start = .;
 
        EXCEPTION_TABLE(8)
@@ -135,8 +135,11 @@ SECTIONS
        _edata = .;
 
        /* BSS */
-       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 8)
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE)
+
+       /* bootmap is allocated in setup_bootmem() directly behind bss. */
 
+       . = ALIGN(HUGEPAGE_SIZE);
        _end = . ;
 
        STABS_DEBUG
index 758ceefb373aedaa0aaa86d57bccfe8fc6390887..134393de69d25e24101e5634d0b538bbf7fbc569 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-y   := init.o fault.o ioremap.o
+obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c
new file mode 100644 (file)
index 0000000..f6fdc77
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * PARISC64 Huge TLB page support.
+ *
+ * This parisc implementation is heavily based on the SPARC and x86 code.
+ *
+ * Copyright (C) 2015 Helge Deller <deller@gmx.de>
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/pagemap.h>
+#include <linux/sysctl.h>
+
+#include <asm/mman.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+
+
+unsigned long
+hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct hstate *h = hstate_file(file);
+
+       if (len & ~huge_page_mask(h))
+               return -EINVAL;
+       if (len > TASK_SIZE)
+               return -ENOMEM;
+
+       if (flags & MAP_FIXED)
+               if (prepare_hugepage_range(file, addr, len))
+                       return -EINVAL;
+
+       if (addr)
+               addr = ALIGN(addr, huge_page_size(h));
+
+       /* we need to make sure the colouring is OK */
+       return arch_get_unmapped_area(file, addr, len, pgoff, flags);
+}
+
+
+pte_t *huge_pte_alloc(struct mm_struct *mm,
+                       unsigned long addr, unsigned long sz)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte = NULL;
+
+       /* We must align the address, because our caller will run
+        * set_huge_pte_at() on whatever we return, which writes out
+        * all of the sub-ptes for the hugepage range.  So we have
+        * to give it the first such sub-pte.
+        */
+       addr &= HPAGE_MASK;
+
+       pgd = pgd_offset(mm, addr);
+       pud = pud_alloc(mm, pgd, addr);
+       if (pud) {
+               pmd = pmd_alloc(mm, pud, addr);
+               if (pmd)
+                       pte = pte_alloc_map(mm, NULL, pmd, addr);
+       }
+       return pte;
+}
+
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte = NULL;
+
+       addr &= HPAGE_MASK;
+
+       pgd = pgd_offset(mm, addr);
+       if (!pgd_none(*pgd)) {
+               pud = pud_offset(pgd, addr);
+               if (!pud_none(*pud)) {
+                       pmd = pmd_offset(pud, addr);
+                       if (!pmd_none(*pmd))
+                               pte = pte_offset_map(pmd, addr);
+               }
+       }
+       return pte;
+}
+
+/* Purge data and instruction TLB entries.  Must be called holding
+ * the pa_tlb_lock.  The TLB purge instructions are slow on SMP
+ * machines since the purge must be broadcast to all CPUs.
+ */
+static inline void purge_tlb_entries_huge(struct mm_struct *mm, unsigned long addr)
+{
+       int i;
+
+       /* We may use multiple physical huge pages (e.g. 2x1 MB) to emulate
+        * Linux standard huge pages (e.g. 2 MB) */
+       BUILD_BUG_ON(REAL_HPAGE_SHIFT > HPAGE_SHIFT);
+
+       addr &= HPAGE_MASK;
+       addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT;
+
+       for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) {
+               mtsp(mm->context, 1);
+               pdtlb(addr);
+               if (unlikely(split_tlb))
+                       pitlb(addr);
+               addr += (1UL << REAL_HPAGE_SHIFT);
+       }
+}
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t entry)
+{
+       unsigned long addr_start;
+       int i;
+
+       addr &= HPAGE_MASK;
+       addr_start = addr;
+
+       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+               /* Directly write pte entry.  We could call set_pte_at(mm, addr, ptep, entry)
+                * instead, but then we get double locking on pa_tlb_lock. */
+               *ptep = entry;
+               ptep++;
+
+               /* Drop the PAGE_SIZE/non-huge tlb entry */
+               purge_tlb_entries(mm, addr);
+
+               addr += PAGE_SIZE;
+               pte_val(entry) += PAGE_SIZE;
+       }
+
+       purge_tlb_entries_huge(mm, addr_start);
+}
+
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep)
+{
+       pte_t entry;
+
+       entry = *ptep;
+       set_huge_pte_at(mm, addr, ptep, __pte(0));
+
+       return entry;
+}
+
+int pmd_huge(pmd_t pmd)
+{
+       return 0;
+}
+
+int pud_huge(pud_t pud)
+{
+       return 0;
+}
index c5fec4890fdf52fe459198ff7780f9e59af6d294..1b366c47768722081efe57a9db39eaba2a7dcde9 100644 (file)
@@ -409,15 +409,11 @@ static void __init map_pages(unsigned long start_vaddr,
        unsigned long vaddr;
        unsigned long ro_start;
        unsigned long ro_end;
-       unsigned long fv_addr;
-       unsigned long gw_addr;
-       extern const unsigned long fault_vector_20;
-       extern void * const linux_gateway_page;
+       unsigned long kernel_end;
 
        ro_start = __pa((unsigned long)_text);
        ro_end   = __pa((unsigned long)&data_start);
-       fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
-       gw_addr  = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
+       kernel_end  = __pa((unsigned long)&_end);
 
        end_paddr = start_paddr + size;
 
@@ -475,24 +471,25 @@ static void __init map_pages(unsigned long start_vaddr,
                        for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) {
                                pte_t pte;
 
-                               /*
-                                * Map the fault vector writable so we can
-                                * write the HPMC checksum.
-                                */
                                if (force)
                                        pte =  __mk_pte(address, pgprot);
-                               else if (parisc_text_address(vaddr) &&
-                                        address != fv_addr)
+                               else if (parisc_text_address(vaddr)) {
                                        pte = __mk_pte(address, PAGE_KERNEL_EXEC);
+                                       if (address >= ro_start && address < kernel_end)
+                                               pte = pte_mkhuge(pte);
+                               }
                                else
 #if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
-                               if (address >= ro_start && address < ro_end
-                                                       && address != fv_addr
-                                                       && address != gw_addr)
-                                       pte = __mk_pte(address, PAGE_KERNEL_RO);
-                               else
+                               if (address >= ro_start && address < ro_end) {
+                                       pte = __mk_pte(address, PAGE_KERNEL_EXEC);
+                                       pte = pte_mkhuge(pte);
+                               } else
 #endif
+                               {
                                        pte = __mk_pte(address, pgprot);
+                                       if (address >= ro_start && address < kernel_end)
+                                               pte = pte_mkhuge(pte);
+                               }
 
                                if (address >= end_paddr) {
                                        if (force)
@@ -536,15 +533,12 @@ void free_initmem(void)
 
        /* force the kernel to see the new TLB entries */
        __flush_tlb_range(0, init_begin, init_end);
-       /* Attempt to catch anyone trying to execute code here
-        * by filling the page with BRK insns.
-        */
-       memset((void *)init_begin, 0x00, init_end - init_begin);
+
        /* finally dump all the instructions which were cached, since the
         * pages are no-longer executable */
        flush_icache_range(init_begin, init_end);
        
-       free_initmem_default(-1);
+       free_initmem_default(POISON_FREE_INITMEM);
 
        /* set up a new led state on systems shipped LED State panel */
        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
@@ -728,8 +722,8 @@ static void __init pagetable_init(void)
                unsigned long size;
 
                start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
-               end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
                size = pmem_ranges[range].pages << PAGE_SHIFT;
+               end_paddr = start_paddr + size;
 
                map_pages((unsigned long)__va(start_paddr), start_paddr,
                          size, PAGE_KERNEL, 0);
index a908ada8e0a5353f5fce19af6ad3e59779ce2e0e..2220f7a60def314be5c8f23e18ceb8982061cb18 100644 (file)
 #define MSR_TS_T       __MASK(MSR_TS_T_LG)     /*  Transaction Transactional */
 #define MSR_TS_MASK    (MSR_TS_T | MSR_TS_S)   /* Transaction State bits */
 #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */
+#define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */
 #define MSR_TM_TRANSACTIONAL(x)        (((x) & MSR_TS_MASK) == MSR_TS_T)
 #define MSR_TM_SUSPENDED(x)    (((x) & MSR_TS_MASK) == MSR_TS_S)
 
index c9e26cb264f49dfff80114ddd97e1d10460157dd..f2b0b1b0c72acf49373310288fcb330d726740e7 100644 (file)
@@ -382,3 +382,4 @@ COMPAT_SYS(shmat)
 SYSCALL(shmdt)
 SYSCALL(shmget)
 COMPAT_SYS(shmctl)
+SYSCALL(mlock2)
index 6d8f8023ac27b1893bd4f6d329c6498b39fd949d..4b6b8ace18e086729932bd5635811167a6491a2b 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          378
+#define __NR_syscalls          379
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 81579e93c65991b3dcb1e129aec6474a722d86cc..1effea5193d6861cb0074a5c682965b4e4f6a13e 100644 (file)
 #define __NR_shmdt             375
 #define __NR_shmget            376
 #define __NR_shmctl            377
+#define __NR_mlock2            378
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 75b6676c1a0b911b72b7af5a8dc7761173e638e8..646bf4d222c1caeda5c7851de74fbbe0ad0d65d9 100644 (file)
@@ -551,6 +551,24 @@ static void tm_reclaim_thread(struct thread_struct *thr,
                msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1;
        }
 
+       /*
+        * Use the current MSR TM suspended bit to track if we have
+        * checkpointed state outstanding.
+        * On signal delivery, we'd normally reclaim the checkpointed
+        * state to obtain stack pointer (see:get_tm_stackpointer()).
+        * This will then directly return to userspace without going
+        * through __switch_to(). However, if the stack frame is bad,
+        * we need to exit this thread which calls __switch_to() which
+        * will again attempt to reclaim the already saved tm state.
+        * Hence we need to check that we've not already reclaimed
+        * this state.
+        * We do this using the current MSR, rather tracking it in
+        * some specific thread_struct bit, as it has the additional
+        * benifit of checking for a potential TM bad thing exception.
+        */
+       if (!MSR_TM_SUSPENDED(mfmsr()))
+               return;
+
        tm_reclaim(thr, thr->regs->msr, cause);
 
        /* Having done the reclaim, we now have the checkpointed
index 0dbee465af7a70e6c1ce0b7f1f667a577a7ebed0..ef7c24e84a623882c8f98dbc93aa7ab318a4ff68 100644 (file)
@@ -875,6 +875,15 @@ static long restore_tm_user_regs(struct pt_regs *regs,
                return 1;
 #endif /* CONFIG_SPE */
 
+       /* Get the top half of the MSR from the user context */
+       if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
+               return 1;
+       msr_hi <<= 32;
+       /* If TM bits are set to the reserved value, it's an invalid context */
+       if (MSR_TM_RESV(msr_hi))
+               return 1;
+       /* Pull in the MSR TM bits from the user context */
+       regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
        /* Now, recheckpoint.  This loads up all of the checkpointed (older)
         * registers, including FP and V[S]Rs.  After recheckpointing, the
         * transactional versions should be loaded.
@@ -884,11 +893,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        current->thread.tm_texasr |= TEXASR_FS;
        /* This loads the checkpointed FP/VEC state, if used */
        tm_recheckpoint(&current->thread, msr);
-       /* Get the top half of the MSR */
-       if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
-               return 1;
-       /* Pull in MSR TM from user context */
-       regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
 
        /* This loads the speculative FP/VEC state, if used */
        if (msr & MSR_FP) {
index 20756dfb9f34620ac254577458ac2aa8ff804835..c676ecec0869b26216e87483f54c2c6906ea6d01 100644 (file)
@@ -438,6 +438,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
 
        /* get MSR separately, transfer the LE bit if doing signal return */
        err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+       /* Don't allow reserved mode. */
+       if (MSR_TM_RESV(msr))
+               return -EINVAL;
+
        /* pull in MSR TM from user context */
        regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
 
index 9c26c5a96ea2bc0ea9d2286f4995b2d629be9003..54b45b73195f912688ec4afe8e9fb4c9c3d5723c 100644 (file)
@@ -2019,7 +2019,7 @@ static bool can_split_piggybacked_subcores(struct core_info *cip)
                        return false;
                n_subcores += (cip->subcore_threads[sub] - 1) >> 1;
        }
-       if (n_subcores > 3 || large_sub < 0)
+       if (large_sub < 0 || !subcore_config_ok(n_subcores + 1, 2))
                return false;
 
        /*
index b1dab8d1d8850cdfcf92d4244e4c688d3d296341..3c6badcd53efced649af69ff9a4adf823b28d9a0 100644 (file)
@@ -1749,7 +1749,8 @@ kvmppc_hdsi:
        beq     3f
        clrrdi  r0, r4, 28
        PPC_SLBFEE_DOT(R5, R0)          /* if so, look up SLB */
-       bne     1f                      /* if no SLB entry found */
+       li      r0, BOOK3S_INTERRUPT_DATA_SEGMENT
+       bne     7f                      /* if no SLB entry found */
 4:     std     r4, VCPU_FAULT_DAR(r9)
        stw     r6, VCPU_FAULT_DSISR(r9)
 
@@ -1768,14 +1769,15 @@ kvmppc_hdsi:
        cmpdi   r3, -2                  /* MMIO emulation; need instr word */
        beq     2f
 
-       /* Synthesize a DSI for the guest */
+       /* Synthesize a DSI (or DSegI) for the guest */
        ld      r4, VCPU_FAULT_DAR(r9)
        mr      r6, r3
-1:     mtspr   SPRN_DAR, r4
+1:     li      r0, BOOK3S_INTERRUPT_DATA_STORAGE
        mtspr   SPRN_DSISR, r6
+7:     mtspr   SPRN_DAR, r4
        mtspr   SPRN_SRR0, r10
        mtspr   SPRN_SRR1, r11
-       li      r10, BOOK3S_INTERRUPT_DATA_STORAGE
+       mr      r10, r0
        bl      kvmppc_msr_interrupt
 fast_interrupt_c_return:
 6:     ld      r7, VCPU_CTR(r9)
@@ -1823,7 +1825,8 @@ kvmppc_hisi:
        beq     3f
        clrrdi  r0, r10, 28
        PPC_SLBFEE_DOT(R5, R0)          /* if so, look up SLB */
-       bne     1f                      /* if no SLB entry found */
+       li      r0, BOOK3S_INTERRUPT_INST_SEGMENT
+       bne     7f                      /* if no SLB entry found */
 4:
        /* Search the hash table. */
        mr      r3, r9                  /* vcpu pointer */
@@ -1840,11 +1843,12 @@ kvmppc_hisi:
        cmpdi   r3, -1                  /* handle in kernel mode */
        beq     guest_exit_cont
 
-       /* Synthesize an ISI for the guest */
+       /* Synthesize an ISI (or ISegI) for the guest */
        mr      r11, r3
-1:     mtspr   SPRN_SRR0, r10
+1:     li      r0, BOOK3S_INTERRUPT_INST_STORAGE
+7:     mtspr   SPRN_SRR0, r10
        mtspr   SPRN_SRR1, r11
-       li      r10, BOOK3S_INTERRUPT_INST_STORAGE
+       mr      r10, r0
        bl      kvmppc_msr_interrupt
        b       fast_interrupt_c_return
 
index 0c5d8ee657f06ecf8537f11ed93e4ecd6e04ee82..d1e7b0a0feeb72649ae71ab8413c7693d022e24c 100644 (file)
@@ -312,6 +312,7 @@ extern void css_schedule_reprobe(void);
 extern void reipl_ccw_dev(struct ccw_dev_id *id);
 
 struct cio_iplinfo {
+       u8 ssid;
        u16 devno;
        int is_qdio;
 };
index 3ad48f22de78c2d846254035c815a3c547d9a595..bab6739a1154e1fd9827ff8dfb5c152ef52f3930 100644 (file)
@@ -206,9 +206,16 @@ do {                                                               \
 } while (0)
 #endif /* CONFIG_COMPAT */
 
-extern unsigned long mmap_rnd_mask;
-
-#define STACK_RND_MASK (test_thread_flag(TIF_31BIT) ? 0x7ff : mmap_rnd_mask)
+/*
+ * Cache aliasing on the latest machines calls for a mapping granularity
+ * of 512KB. For 64-bit processes use a 512KB alignment and a randomization
+ * of up to 1GB. For 31-bit processes the virtual address space is limited,
+ * use no alignment and limit the randomization to 8MB.
+ */
+#define BRK_RND_MASK   (is_32bit_task() ? 0x7ffUL : 0x3ffffUL)
+#define MMAP_RND_MASK  (is_32bit_task() ? 0x7ffUL : 0x3ff80UL)
+#define MMAP_ALIGN_MASK        (is_32bit_task() ? 0 : 0x7fUL)
+#define STACK_RND_MASK MMAP_RND_MASK
 
 #define ARCH_DLINFO                                                        \
 do {                                                                       \
index 39ae6a3597478117e1c6328382e034a59b527c77..86634e71b69f4ec880c9c237d51b1626a69148b0 100644 (file)
@@ -64,7 +64,8 @@ struct ipl_block_fcp {
 
 struct ipl_block_ccw {
        u8  reserved1[84];
-       u8  reserved2[2];
+       u16 reserved2 : 13;
+       u8  ssid : 3;
        u16 devno;
        u8  vm_flags;
        u8  reserved3[3];
index 7a7abf1a5537242746b079bfb57dfe555a1e6b33..1aac41e83ea197121c5dd178c587323f9b875aa1 100644 (file)
@@ -195,5 +195,7 @@ void zpci_dma_exit_device(struct zpci_dev *);
 void dma_free_seg_table(unsigned long);
 unsigned long *dma_alloc_cpu_table(void);
 void dma_cleanup_tables(unsigned long *);
-void dma_update_cpu_trans(unsigned long *, void *, dma_addr_t, int);
+unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr);
+void dma_update_cpu_trans(unsigned long *entry, void *page_addr, int flags);
+
 #endif
index 776f307960cc877a80edda1e41f5ed6f1d94a6c4..cc6cfe7889da5351057c1f036b5ca293a0f8bffa 100644 (file)
@@ -19,7 +19,7 @@
 #define TRACE_INCLUDE_PATH asm/trace
 #define TRACE_INCLUDE_FILE diag
 
-TRACE_EVENT(diagnose,
+TRACE_EVENT(s390_diagnose,
        TP_PROTO(unsigned short nr),
        TP_ARGS(nr),
        TP_STRUCT__entry(
@@ -32,9 +32,9 @@ TRACE_EVENT(diagnose,
 );
 
 #ifdef CONFIG_TRACEPOINTS
-void trace_diagnose_norecursion(int diag_nr);
+void trace_s390_diagnose_norecursion(int diag_nr);
 #else
-static inline void trace_diagnose_norecursion(int diag_nr) { }
+static inline void trace_s390_diagnose_norecursion(int diag_nr) { }
 #endif
 
 #endif /* _TRACE_S390_DIAG_H */
index a848adba1504a1c9b758d55ef3b44ee07bc74471..34ec202472c6cadb5b973b54c6c995bb6d2e897c 100644 (file)
 #define __NR_set_tid_address   252
 #define __NR_fadvise64         253
 #define __NR_timer_create      254
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_timer_settime     255
+#define __NR_timer_gettime     256
+#define __NR_timer_getoverrun  257
+#define __NR_timer_delete      258
+#define __NR_clock_settime     259
+#define __NR_clock_gettime     260
+#define __NR_clock_getres      261
+#define __NR_clock_nanosleep   262
 /* Number 263 is reserved for vserver */
 #define __NR_statfs64          265
 #define __NR_fstatfs64         266
 #define __NR_recvfrom          371
 #define __NR_recvmsg           372
 #define __NR_shutdown          373
-#define NR_syscalls 374
+#define __NR_mlock2            374
+#define NR_syscalls 375
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 09f194052df35f712cff3fe8f44639df9de6c9e1..fac4eeddef91fe3acb21e0108069f3f3a70ef72a 100644 (file)
@@ -176,3 +176,4 @@ COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
 COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
 COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
+COMPAT_SYSCALL_WRAP3(mlock2, unsigned long, start, size_t, len, int, flags);
index f98766ede4e156e83dc222194ed677150b891c64..48b37b8357e6838dd213f230eaaf274027193b74 100644 (file)
@@ -121,14 +121,14 @@ device_initcall(show_diag_stat_init);
 void diag_stat_inc(enum diag_stat_enum nr)
 {
        this_cpu_inc(diag_stat.counter[nr]);
-       trace_diagnose(diag_map[nr].code);
+       trace_s390_diagnose(diag_map[nr].code);
 }
 EXPORT_SYMBOL(diag_stat_inc);
 
 void diag_stat_inc_norecursion(enum diag_stat_enum nr)
 {
        this_cpu_inc(diag_stat.counter[nr]);
-       trace_diagnose_norecursion(diag_map[nr].code);
+       trace_s390_diagnose_norecursion(diag_map[nr].code);
 }
 EXPORT_SYMBOL(diag_stat_inc_norecursion);
 
index 1255c6c5353e2404f065545e557fe216e109b127..301ee9c70688b7ef35db09a62c9b8f3524ed5e68 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/ptrace.h>
 
 #define ARCH_OFFSET    4
 
@@ -59,19 +60,6 @@ __HEAD
        .long   0x020006e0,0x20000050
 
        .org    0x200
-#
-# subroutine to set architecture mode
-#
-.Lsetmode:
-       mvi     __LC_AR_MODE_ID,1       # set esame flag
-       slr     %r0,%r0                 # set cpuid to zero
-       lhi     %r1,2                   # mode 2 = esame (dump)
-       sigp    %r1,%r0,0x12            # switch to esame mode
-       bras    %r13,0f
-       .fill   16,4,0x0
-0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
-       sam31                           # switch to 31 bit addressing mode
-       br      %r14
 
 #
 # subroutine to wait for end I/O
@@ -159,7 +147,14 @@ __HEAD
        .long   0x02200050,0x00000000
 
 iplstart:
-       bas     %r14,.Lsetmode          # Immediately switch to 64 bit mode
+       mvi     __LC_AR_MODE_ID,1       # set esame flag
+       slr     %r0,%r0                 # set cpuid to zero
+       lhi     %r1,2                   # mode 2 = esame (dump)
+       sigp    %r1,%r0,0x12            # switch to esame mode
+       bras    %r13,0f
+       .fill   16,4,0x0
+0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
+       sam31                           # switch to 31 bit addressing mode
        lh      %r1,0xb8                # test if subchannel number
        bct     %r1,.Lnoload            #  is valid
        l       %r1,0xb8                # load ipl subchannel number
@@ -268,71 +263,6 @@ iplstart:
        .align  8
 .Lcpuid:.fill  8,1,0
 
-#
-# SALIPL loader support. Based on a patch by Rob van der Heij.
-# This entry point is called directly from the SALIPL loader and
-# doesn't need a builtin ipl record.
-#
-       .org    0x800
-ENTRY(start)
-       stm     %r0,%r15,0x07b0         # store registers
-       bas     %r14,.Lsetmode          # Immediately switch to 64 bit mode
-       basr    %r12,%r0
-.base:
-       l       %r11,.parm
-       l       %r8,.cmd                # pointer to command buffer
-
-       ltr     %r9,%r9                 # do we have SALIPL parameters?
-       bp      .sk8x8
-
-       mvc     0(64,%r8),0x00b0        # copy saved registers
-       xc      64(240-64,%r8),0(%r8)   # remainder of buffer
-       tr      0(64,%r8),.lowcase
-       b       .gotr
-.sk8x8:
-       mvc     0(240,%r8),0(%r9)       # copy iplparms into buffer
-.gotr:
-       slr     %r0,%r0
-       st      %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
-       st      %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
-       j       startup                 # continue with startup
-.cmd:  .long   COMMAND_LINE            # address of command line buffer
-.parm: .long   PARMAREA
-.lowcase:
-       .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
-       .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
-       .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
-       .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
-       .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
-       .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
-       .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
-       .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
-       .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
-       .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
-       .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
-       .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
-       .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
-       .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
-       .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
-       .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
-
-       .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
-       .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
-       .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
-       .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
-       .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
-       .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
-       .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
-       .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
-       .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87   # .abcdefg
-       .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf   # hi
-       .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97   # .jklmnop
-       .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf   # qr
-       .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7   # ..stuvwx
-       .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef   # yz
-       .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
-       .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-
 #
 # startup-code at 0x10000, running in absolute addressing mode
 # this is called either by the ipl loader or directly by PSW restart
@@ -364,7 +294,7 @@ ENTRY(startup_kdump)
        bras    %r13,0f
        .fill   16,4,0x0
 0:     lmh     %r0,%r15,0(%r13)        # clear high-order half of gprs
-       sam31                           # switch to 31 bit addressing mode
+       sam64                           # switch to 64 bit addressing mode
        basr    %r13,0                  # get base
 .LPG0:
        xc      0x200(256),0x200        # partially clear lowcore
@@ -395,7 +325,7 @@ ENTRY(startup_kdump)
        jnz     1b
        j       4f
 2:     l       %r15,.Lstack-.LPG0(%r13)
-       ahi     %r15,-96
+       ahi     %r15,-STACK_FRAME_OVERHEAD
        la      %r2,.Lals_string-.LPG0(%r13)
        l       %r3,.Lsclp_print-.LPG0(%r13)
        basr    %r14,%r3
@@ -429,8 +359,7 @@ ENTRY(startup_kdump)
        .long 1, 0xc0000000
 #endif
 4:
-       /* Continue with 64bit startup code in head64.S */
-       sam64                           # switch to 64 bit mode
+       /* Continue with startup code in head64.S */
        jg      startup_continue
 
        .align  8
index f6d8acd7e13654c307a5d54e80bd6e084cf04a13..b1f0a90f933bbc95cc04c9e028d87865555909a9 100644 (file)
@@ -121,6 +121,7 @@ static char *dump_type_str(enum dump_type type)
  * Must be in data section since the bss section
  * is not cleared when these are accessed.
  */
+static u8 ipl_ssid __attribute__((__section__(".data"))) = 0;
 static u16 ipl_devno __attribute__((__section__(".data"))) = 0;
 u32 ipl_flags __attribute__((__section__(".data"))) = 0;
 
@@ -197,6 +198,33 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj,        \
        return snprintf(page, PAGE_SIZE, _format, ##args);              \
 }
 
+#define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk)                        \
+static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,   \
+               struct kobj_attribute *attr,                            \
+               const char *buf, size_t len)                            \
+{                                                                      \
+       unsigned long long ssid, devno;                                 \
+                                                                       \
+       if (sscanf(buf, "0.%llx.%llx\n", &ssid, &devno) != 2)           \
+               return -EINVAL;                                         \
+                                                                       \
+       if (ssid > __MAX_SSID || devno > __MAX_SUBCHANNEL)              \
+               return -EINVAL;                                         \
+                                                                       \
+       _ipl_blk.ssid = ssid;                                           \
+       _ipl_blk.devno = devno;                                         \
+       return len;                                                     \
+}
+
+#define DEFINE_IPL_CCW_ATTR_RW(_prefix, _name, _ipl_blk)               \
+IPL_ATTR_SHOW_FN(_prefix, _name, "0.%x.%04x\n",                                \
+                _ipl_blk.ssid, _ipl_blk.devno);                        \
+IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk);                       \
+static struct kobj_attribute sys_##_prefix##_##_name##_attr =          \
+       __ATTR(_name, (S_IRUGO | S_IWUSR),                              \
+              sys_##_prefix##_##_name##_show,                          \
+              sys_##_prefix##_##_name##_store)                         \
+
 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)            \
 IPL_ATTR_SHOW_FN(_prefix, _name, _format, _value)                      \
 static struct kobj_attribute sys_##_prefix##_##_name##_attr =          \
@@ -395,7 +423,7 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj,
 
        switch (ipl_info.type) {
        case IPL_TYPE_CCW:
-               return sprintf(page, "0.0.%04x\n", ipl_devno);
+               return sprintf(page, "0.%x.%04x\n", ipl_ssid, ipl_devno);
        case IPL_TYPE_FCP:
        case IPL_TYPE_FCP_DUMP:
                return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno);
@@ -687,21 +715,14 @@ static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
                                       struct bin_attribute *attr,
                                       char *buf, loff_t off, size_t count)
 {
+       size_t scpdata_len = count;
        size_t padding;
-       size_t scpdata_len;
-
-       if (off < 0)
-               return -EINVAL;
 
-       if (off >= DIAG308_SCPDATA_SIZE)
-               return -ENOSPC;
 
-       if (count > DIAG308_SCPDATA_SIZE - off)
-               count = DIAG308_SCPDATA_SIZE - off;
-
-       memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf + off, count);
-       scpdata_len = off + count;
+       if (off)
+               return -EINVAL;
 
+       memcpy(reipl_block_fcp->ipl_info.fcp.scp_data, buf, count);
        if (scpdata_len % 8) {
                padding = 8 - (scpdata_len % 8);
                memset(reipl_block_fcp->ipl_info.fcp.scp_data + scpdata_len,
@@ -717,7 +738,7 @@ static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
 }
 static struct bin_attribute sys_reipl_fcp_scp_data_attr =
        __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_fcp_scpdata_read,
-                  reipl_fcp_scpdata_write, PAGE_SIZE);
+                  reipl_fcp_scpdata_write, DIAG308_SCPDATA_SIZE);
 
 static struct bin_attribute *reipl_fcp_bin_attrs[] = {
        &sys_reipl_fcp_scp_data_attr,
@@ -814,9 +835,7 @@ static struct attribute_group reipl_fcp_attr_group = {
 };
 
 /* CCW reipl device attributes */
-
-DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-       reipl_block_ccw->ipl_info.ccw.devno);
+DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ipl_info.ccw);
 
 /* NSS wrapper */
 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
@@ -1056,8 +1075,8 @@ static void __reipl_run(void *unused)
 
        switch (reipl_method) {
        case REIPL_METHOD_CCW_CIO:
+               devid.ssid  = reipl_block_ccw->ipl_info.ccw.ssid;
                devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
-               devid.ssid  = 0;
                reipl_ccw_dev(&devid);
                break;
        case REIPL_METHOD_CCW_VM:
@@ -1192,6 +1211,7 @@ static int __init reipl_ccw_init(void)
 
        reipl_block_ccw_init(reipl_block_ccw);
        if (ipl_info.type == IPL_TYPE_CCW) {
+               reipl_block_ccw->ipl_info.ccw.ssid = ipl_ssid;
                reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
                reipl_block_ccw_fill_parms(reipl_block_ccw);
        }
@@ -1336,9 +1356,7 @@ static struct attribute_group dump_fcp_attr_group = {
 };
 
 /* CCW dump device attributes */
-
-DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-                  dump_block_ccw->ipl_info.ccw.devno);
+DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ipl_info.ccw);
 
 static struct attribute *dump_ccw_attrs[] = {
        &sys_dump_ccw_device_attr.attr,
@@ -1418,8 +1436,8 @@ static void __dump_run(void *unused)
 
        switch (dump_method) {
        case DUMP_METHOD_CCW_CIO:
+               devid.ssid  = dump_block_ccw->ipl_info.ccw.ssid;
                devid.devno = dump_block_ccw->ipl_info.ccw.devno;
-               devid.ssid  = 0;
                reipl_ccw_dev(&devid);
                break;
        case DUMP_METHOD_CCW_VM:
@@ -1939,14 +1957,14 @@ void __init setup_ipl(void)
        ipl_info.type = get_ipl_type();
        switch (ipl_info.type) {
        case IPL_TYPE_CCW:
+               ipl_info.data.ccw.dev_id.ssid = ipl_ssid;
                ipl_info.data.ccw.dev_id.devno = ipl_devno;
-               ipl_info.data.ccw.dev_id.ssid = 0;
                break;
        case IPL_TYPE_FCP:
        case IPL_TYPE_FCP_DUMP:
+               ipl_info.data.fcp.dev_id.ssid = 0;
                ipl_info.data.fcp.dev_id.devno =
                        IPL_PARMBLOCK_START->ipl_info.fcp.devno;
-               ipl_info.data.fcp.dev_id.ssid = 0;
                ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn;
                ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun;
                break;
@@ -1978,6 +1996,7 @@ void __init ipl_save_parameters(void)
        if (cio_get_iplinfo(&iplinfo))
                return;
 
+       ipl_ssid = iplinfo.ssid;
        ipl_devno = iplinfo.devno;
        ipl_flags |= IPL_DEVNO_VALID;
        if (!iplinfo.is_qdio)
index 688a3aad9c79d02a49702f729c3b418065c982e3..114ee8b96f17d31d5dba657c704bc34a2e1b9a9e 100644 (file)
@@ -243,11 +243,7 @@ unsigned long arch_align_stack(unsigned long sp)
 
 static inline unsigned long brk_rnd(void)
 {
-       /* 8MB for 32bit, 1GB for 64bit */
-       if (is_32bit_task())
-               return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
-       else
-               return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
+       return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
 }
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)
index fa0bdff1d41305cb61fdc160d381a509ec4a53b7..9fe7781a45cdd7717e4a65af365f1a24d69812da 100644 (file)
@@ -21,7 +21,7 @@ static void _sclp_wait_int(void)
        __ctl_load(cr0_new, 0, 0);
 
        psw_ext_save = S390_lowcore.external_new_psw;
-       psw_mask = __extract_psw() & (PSW_MASK_EA | PSW_MASK_BA);
+       psw_mask = __extract_psw();
        S390_lowcore.external_new_psw.mask = psw_mask;
        psw_wait.mask = psw_mask | PSW_MASK_EXT | PSW_MASK_WAIT;
        S390_lowcore.ext_int_code = 0;
index ce0cbd6ba7ca9e5a8ca4b0cf05b37ea2a1e5dcc0..c837bcacf2188460a50754f3a75d1b485c25f671 100644 (file)
@@ -764,9 +764,6 @@ static int __init setup_hwcaps(void)
        get_cpu_id(&cpu_id);
        add_device_randomness(&cpu_id, sizeof(cpu_id));
        switch (cpu_id.machine) {
-       case 0x9672:
-               strcpy(elf_platform, "g5");
-               break;
        case 0x2064:
        case 0x2066:
        default:        /* Use "z900" as default for 64 bit kernels. */
index 8c56929c8d826e09ccd3620454b813101cb319e7..5378c3ea1b984918ed3719c8a9cf8d1c8c86574a 100644 (file)
@@ -382,3 +382,4 @@ SYSCALL(sys_sendmsg,compat_sys_sendmsg)                     /* 370 */
 SYSCALL(sys_recvfrom,compat_sys_recvfrom)
 SYSCALL(sys_recvmsg,compat_sys_recvmsg)
 SYSCALL(sys_shutdown,sys_shutdown)
+SYSCALL(sys_mlock2,compat_sys_mlock2)
index 73239bb576c4ee8aaa69b232cdea0cbbd7f91fd0..21a5df99552bce6e4f84c872acdda43e6c5732c3 100644 (file)
@@ -9,11 +9,11 @@
 #define CREATE_TRACE_POINTS
 #include <asm/trace/diag.h>
 
-EXPORT_TRACEPOINT_SYMBOL(diagnose);
+EXPORT_TRACEPOINT_SYMBOL(s390_diagnose);
 
 static DEFINE_PER_CPU(unsigned int, diagnose_trace_depth);
 
-void trace_diagnose_norecursion(int diag_nr)
+void trace_s390_diagnose_norecursion(int diag_nr)
 {
        unsigned long flags;
        unsigned int *depth;
@@ -22,7 +22,7 @@ void trace_diagnose_norecursion(int diag_nr)
        depth = this_cpu_ptr(&diagnose_trace_depth);
        if (*depth == 0) {
                (*depth)++;
-               trace_diagnose(diag_nr);
+               trace_s390_diagnose(diag_nr);
                (*depth)--;
        }
        local_irq_restore(flags);
index 373e32346d68d6c3ae270ca39b96b09fe66b0a6e..6a75352f453c1a46775112c2749b8cff31d62ed1 100644 (file)
@@ -1030,8 +1030,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
                                   src_id, 0);
 
        /* sending vcpu invalid */
-       if (src_id >= KVM_MAX_VCPUS ||
-           kvm_get_vcpu(vcpu->kvm, src_id) == NULL)
+       if (kvm_get_vcpu_by_id(vcpu->kvm, src_id) == NULL)
                return -EINVAL;
 
        if (sclp.has_sigpif)
@@ -1110,6 +1109,10 @@ static int __inject_sigp_emergency(struct kvm_vcpu *vcpu,
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
                                   irq->u.emerg.code, 0);
 
+       /* sending vcpu invalid */
+       if (kvm_get_vcpu_by_id(vcpu->kvm, irq->u.emerg.code) == NULL)
+               return -EINVAL;
+
        set_bit(irq->u.emerg.code, li->sigp_emerg_pending);
        set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
        atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
index 8fe2f1c722dcabe22b3b3731bdce5e22092703db..846589281b046f414837cbd3f7ab9f4d0c675a51 100644 (file)
@@ -342,12 +342,16 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                r = 0;
                break;
        case KVM_CAP_S390_VECTOR_REGISTERS:
-               if (MACHINE_HAS_VX) {
+               mutex_lock(&kvm->lock);
+               if (atomic_read(&kvm->online_vcpus)) {
+                       r = -EBUSY;
+               } else if (MACHINE_HAS_VX) {
                        set_kvm_facility(kvm->arch.model.fac->mask, 129);
                        set_kvm_facility(kvm->arch.model.fac->list, 129);
                        r = 0;
                } else
                        r = -EINVAL;
+               mutex_unlock(&kvm->lock);
                VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
                         r ? "(not available)" : "(success)");
                break;
index 77191b85ea7af4dd96dc6a1ae819f27faa25233b..d76b51cb4b6207261e495bad832ec07444ec11a5 100644 (file)
@@ -660,7 +660,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
 
        kvm_s390_get_regs_rre(vcpu, &reg1, &reg2);
 
-       if (!MACHINE_HAS_PFMF)
+       if (!test_kvm_facility(vcpu->kvm, 8))
                return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
index da690b69f9fe17a89c3f1dc3cd1b1119b832bd25..77c22d685c7a150a8ecfdccbfca1ec60f08698af 100644 (file)
@@ -291,12 +291,8 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
                           u16 cpu_addr, u32 parameter, u64 *status_reg)
 {
        int rc;
-       struct kvm_vcpu *dst_vcpu;
+       struct kvm_vcpu *dst_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr);
 
-       if (cpu_addr >= KVM_MAX_VCPUS)
-               return SIGP_CC_NOT_OPERATIONAL;
-
-       dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
        if (!dst_vcpu)
                return SIGP_CC_NOT_OPERATIONAL;
 
@@ -478,7 +474,7 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu)
        trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr);
 
        if (order_code == SIGP_EXTERNAL_CALL) {
-               dest_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr);
+               dest_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr);
                BUG_ON(dest_vcpu == NULL);
 
                kvm_s390_vcpu_wakeup(dest_vcpu);
index c3c07d3505ba17ebe953d4310508abeb6b63fba1..c722400c769784d8df6f13507693e117ad942497 100644 (file)
@@ -48,37 +48,13 @@ EXPORT_SYMBOL(zero_page_mask);
 
 static void __init setup_zero_pages(void)
 {
-       struct cpuid cpu_id;
        unsigned int order;
        struct page *page;
        int i;
 
-       get_cpu_id(&cpu_id);
-       switch (cpu_id.machine) {
-       case 0x9672:    /* g5 */
-       case 0x2064:    /* z900 */
-       case 0x2066:    /* z900 */
-       case 0x2084:    /* z990 */
-       case 0x2086:    /* z990 */
-       case 0x2094:    /* z9-109 */
-       case 0x2096:    /* z9-109 */
-               order = 0;
-               break;
-       case 0x2097:    /* z10 */
-       case 0x2098:    /* z10 */
-       case 0x2817:    /* z196 */
-       case 0x2818:    /* z196 */
-               order = 2;
-               break;
-       case 0x2827:    /* zEC12 */
-       case 0x2828:    /* zEC12 */
-               order = 5;
-               break;
-       case 0x2964:    /* z13 */
-       default:
-               order = 7;
-               break;
-       }
+       /* Latest machines require a mapping granularity of 512KB */
+       order = 7;
+
        /* Limit number of empty zero pages for small memory sizes */
        while (order > 2 && (totalram_pages >> 10) < (1UL << order))
                order--;
index 6e552af08c76a61027c023f7305133ee1b4efe02..ea01477b4aa67155f87b88e8c6a87f5374eda247 100644 (file)
@@ -31,9 +31,6 @@
 #include <linux/security.h>
 #include <asm/pgalloc.h>
 
-unsigned long mmap_rnd_mask;
-static unsigned long mmap_align_mask;
-
 static unsigned long stack_maxrandom_size(void)
 {
        if (!(current->flags & PF_RANDOMIZE))
@@ -62,10 +59,7 @@ static inline int mmap_is_legacy(void)
 
 unsigned long arch_mmap_rnd(void)
 {
-       if (is_32bit_task())
-               return (get_random_int() & 0x7ff) << PAGE_SHIFT;
-       else
-               return (get_random_int() & mmap_rnd_mask) << PAGE_SHIFT;
+       return (get_random_int() & MMAP_RND_MASK) << PAGE_SHIFT;
 }
 
 static unsigned long mmap_base_legacy(unsigned long rnd)
@@ -92,7 +86,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        struct vm_unmapped_area_info info;
-       int do_color_align;
 
        if (len > TASK_SIZE - mmap_min_addr)
                return -ENOMEM;
@@ -108,15 +101,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                        return addr;
        }
 
-       do_color_align = 0;
-       if (filp || (flags & MAP_SHARED))
-               do_color_align = !is_32bit_task();
-
        info.flags = 0;
        info.length = len;
        info.low_limit = mm->mmap_base;
        info.high_limit = TASK_SIZE;
-       info.align_mask = do_color_align ? (mmap_align_mask << PAGE_SHIFT) : 0;
+       if (filp || (flags & MAP_SHARED))
+               info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT;
+       else
+               info.align_mask = 0;
        info.align_offset = pgoff << PAGE_SHIFT;
        return vm_unmapped_area(&info);
 }
@@ -130,7 +122,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        struct mm_struct *mm = current->mm;
        unsigned long addr = addr0;
        struct vm_unmapped_area_info info;
-       int do_color_align;
 
        /* requested length too big for entire address space */
        if (len > TASK_SIZE - mmap_min_addr)
@@ -148,15 +139,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        return addr;
        }
 
-       do_color_align = 0;
-       if (filp || (flags & MAP_SHARED))
-               do_color_align = !is_32bit_task();
-
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
        info.low_limit = max(PAGE_SIZE, mmap_min_addr);
        info.high_limit = mm->mmap_base;
-       info.align_mask = do_color_align ? (mmap_align_mask << PAGE_SHIFT) : 0;
+       if (filp || (flags & MAP_SHARED))
+               info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT;
+       else
+               info.align_mask = 0;
        info.align_offset = pgoff << PAGE_SHIFT;
        addr = vm_unmapped_area(&info);
 
@@ -254,35 +244,3 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
                mm->get_unmapped_area = s390_get_unmapped_area_topdown;
        }
 }
-
-static int __init setup_mmap_rnd(void)
-{
-       struct cpuid cpu_id;
-
-       get_cpu_id(&cpu_id);
-       switch (cpu_id.machine) {
-       case 0x9672:
-       case 0x2064:
-       case 0x2066:
-       case 0x2084:
-       case 0x2086:
-       case 0x2094:
-       case 0x2096:
-       case 0x2097:
-       case 0x2098:
-       case 0x2817:
-       case 0x2818:
-       case 0x2827:
-       case 0x2828:
-               mmap_rnd_mask = 0x7ffUL;
-               mmap_align_mask = 0UL;
-               break;
-       case 0x2964:    /* z13 */
-       default:
-               mmap_rnd_mask = 0x3ff80UL;
-               mmap_align_mask = 0x7fUL;
-               break;
-       }
-       return 0;
-}
-early_initcall(setup_mmap_rnd);
index 37d10f74425a453202ae11e232d361404e9e68c2..d348f2c09a1eede659378cf4ae2686df008e4bd8 100644 (file)
@@ -33,7 +33,7 @@ unsigned long *dma_alloc_cpu_table(void)
                return NULL;
 
        for (entry = table; entry < table + ZPCI_TABLE_ENTRIES; entry++)
-               *entry = ZPCI_TABLE_INVALID | ZPCI_TABLE_PROTECTED;
+               *entry = ZPCI_TABLE_INVALID;
        return table;
 }
 
@@ -51,7 +51,7 @@ static unsigned long *dma_alloc_page_table(void)
                return NULL;
 
        for (entry = table; entry < table + ZPCI_PT_ENTRIES; entry++)
-               *entry = ZPCI_PTE_INVALID | ZPCI_TABLE_PROTECTED;
+               *entry = ZPCI_PTE_INVALID;
        return table;
 }
 
@@ -95,7 +95,7 @@ static unsigned long *dma_get_page_table_origin(unsigned long *entry)
        return pto;
 }
 
-static unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr)
+unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr)
 {
        unsigned long *sto, *pto;
        unsigned int rtx, sx, px;
@@ -114,20 +114,10 @@ static unsigned long *dma_walk_cpu_trans(unsigned long *rto, dma_addr_t dma_addr
        return &pto[px];
 }
 
-void dma_update_cpu_trans(unsigned long *dma_table, void *page_addr,
-                         dma_addr_t dma_addr, int flags)
+void dma_update_cpu_trans(unsigned long *entry, void *page_addr, int flags)
 {
-       unsigned long *entry;
-
-       entry = dma_walk_cpu_trans(dma_table, dma_addr);
-       if (!entry) {
-               WARN_ON_ONCE(1);
-               return;
-       }
-
        if (flags & ZPCI_PTE_INVALID) {
                invalidate_pt_entry(entry);
-               return;
        } else {
                set_pt_pfaa(entry, page_addr);
                validate_pt_entry(entry);
@@ -146,18 +136,25 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
        u8 *page_addr = (u8 *) (pa & PAGE_MASK);
        dma_addr_t start_dma_addr = dma_addr;
        unsigned long irq_flags;
+       unsigned long *entry;
        int i, rc = 0;
 
        if (!nr_pages)
                return -EINVAL;
 
        spin_lock_irqsave(&zdev->dma_table_lock, irq_flags);
-       if (!zdev->dma_table)
+       if (!zdev->dma_table) {
+               rc = -EINVAL;
                goto no_refresh;
+       }
 
        for (i = 0; i < nr_pages; i++) {
-               dma_update_cpu_trans(zdev->dma_table, page_addr, dma_addr,
-                                    flags);
+               entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr);
+               if (!entry) {
+                       rc = -ENOMEM;
+                       goto undo_cpu_trans;
+               }
+               dma_update_cpu_trans(entry, page_addr, flags);
                page_addr += PAGE_SIZE;
                dma_addr += PAGE_SIZE;
        }
@@ -176,6 +173,18 @@ static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
 
        rc = zpci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
                                nr_pages * PAGE_SIZE);
+undo_cpu_trans:
+       if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)) {
+               flags = ZPCI_PTE_INVALID;
+               while (i-- > 0) {
+                       page_addr -= PAGE_SIZE;
+                       dma_addr -= PAGE_SIZE;
+                       entry = dma_walk_cpu_trans(zdev->dma_table, dma_addr);
+                       if (!entry)
+                               break;
+                       dma_update_cpu_trans(entry, page_addr, flags);
+               }
+       }
 
 no_refresh:
        spin_unlock_irqrestore(&zdev->dma_table_lock, irq_flags);
@@ -260,6 +269,16 @@ static void dma_free_iommu(struct zpci_dev *zdev, unsigned long offset, int size
        spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, flags);
 }
 
+static inline void zpci_err_dma(unsigned long rc, unsigned long addr)
+{
+       struct {
+               unsigned long rc;
+               unsigned long addr;
+       } __packed data = {rc, addr};
+
+       zpci_err_hex(&data, sizeof(data));
+}
+
 static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
                                     unsigned long offset, size_t size,
                                     enum dma_data_direction direction,
@@ -270,33 +289,40 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
        unsigned long pa = page_to_phys(page) + offset;
        int flags = ZPCI_PTE_VALID;
        dma_addr_t dma_addr;
+       int ret;
 
        /* This rounds up number of pages based on size and offset */
        nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
        iommu_page_index = dma_alloc_iommu(zdev, nr_pages);
-       if (iommu_page_index == -1)
+       if (iommu_page_index == -1) {
+               ret = -ENOSPC;
                goto out_err;
+       }
 
        /* Use rounded up size */
        size = nr_pages * PAGE_SIZE;
 
        dma_addr = zdev->start_dma + iommu_page_index * PAGE_SIZE;
-       if (dma_addr + size > zdev->end_dma)
+       if (dma_addr + size > zdev->end_dma) {
+               ret = -ERANGE;
                goto out_free;
+       }
 
        if (direction == DMA_NONE || direction == DMA_TO_DEVICE)
                flags |= ZPCI_TABLE_PROTECTED;
 
-       if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) {
-               atomic64_add(nr_pages, &zdev->mapped_pages);
-               return dma_addr + (offset & ~PAGE_MASK);
-       }
+       ret = dma_update_trans(zdev, pa, dma_addr, size, flags);
+       if (ret)
+               goto out_free;
+
+       atomic64_add(nr_pages, &zdev->mapped_pages);
+       return dma_addr + (offset & ~PAGE_MASK);
 
 out_free:
        dma_free_iommu(zdev, iommu_page_index, nr_pages);
 out_err:
        zpci_err("map error:\n");
-       zpci_err_hex(&pa, sizeof(pa));
+       zpci_err_dma(ret, pa);
        return DMA_ERROR_CODE;
 }
 
@@ -306,14 +332,16 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
 {
        struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long iommu_page_index;
-       int npages;
+       int npages, ret;
 
        npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
        dma_addr = dma_addr & PAGE_MASK;
-       if (dma_update_trans(zdev, 0, dma_addr, npages * PAGE_SIZE,
-                            ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID)) {
+       ret = dma_update_trans(zdev, 0, dma_addr, npages * PAGE_SIZE,
+                              ZPCI_PTE_INVALID);
+       if (ret) {
                zpci_err("unmap error:\n");
-               zpci_err_hex(&dma_addr, sizeof(dma_addr));
+               zpci_err_dma(ret, dma_addr);
+               return;
        }
 
        atomic64_add(npages, &zdev->unmapped_pages);
index ccffa53750a89283feae5c1ea8b10f7e99cf57ea..39bcefc20de73d2d8a5693586204609f1cf70279 100644 (file)
@@ -60,6 +60,7 @@ struct legacy_pic {
        void (*mask_all)(void);
        void (*restore_mask)(void);
        void (*init)(int auto_eoi);
+       int (*probe)(void);
        int (*irq_pending)(unsigned int irq);
        void (*make_irq)(unsigned int irq);
 };
index 9265196e877f34d662ea56a8d5993dcb4349ea57..30cfd64295a0075ab9c4727721c0fc8c8b607f46 100644 (file)
@@ -505,6 +505,7 @@ struct kvm_vcpu_arch {
        u32 virtual_tsc_mult;
        u32 virtual_tsc_khz;
        s64 ia32_tsc_adjust_msr;
+       u64 tsc_scaling_ratio;
 
        atomic_t nmi_queued;  /* unprocessed asynchronous NMIs */
        unsigned nmi_pending; /* NMI queued after currently running handler */
@@ -777,7 +778,7 @@ struct kvm_x86_ops {
        void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
        void (*vcpu_put)(struct kvm_vcpu *vcpu);
 
-       void (*update_db_bp_intercept)(struct kvm_vcpu *vcpu);
+       void (*update_bp_intercept)(struct kvm_vcpu *vcpu);
        int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr);
        int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr);
        u64 (*get_segment_base)(struct kvm_vcpu *vcpu, int seg);
@@ -844,7 +845,7 @@ struct kvm_x86_ops {
        int (*get_lpage_level)(void);
        bool (*rdtscp_supported)(void);
        bool (*invpcid_supported)(void);
-       void (*adjust_tsc_offset)(struct kvm_vcpu *vcpu, s64 adjustment, bool host);
+       void (*adjust_tsc_offset_guest)(struct kvm_vcpu *vcpu, s64 adjustment);
 
        void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
 
@@ -852,11 +853,9 @@ struct kvm_x86_ops {
 
        bool (*has_wbinvd_exit)(void);
 
-       void (*set_tsc_khz)(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale);
        u64 (*read_tsc_offset)(struct kvm_vcpu *vcpu);
        void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
-       u64 (*compute_tsc_offset)(struct kvm_vcpu *vcpu, u64 target_tsc);
        u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu, u64 host_tsc);
 
        void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
@@ -923,17 +922,6 @@ struct kvm_arch_async_pf {
 
 extern struct kvm_x86_ops *kvm_x86_ops;
 
-static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
-                                          s64 adjustment)
-{
-       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, false);
-}
-
-static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
-{
-       kvm_x86_ops->adjust_tsc_offset(vcpu, adjustment, true);
-}
-
 int kvm_mmu_module_init(void);
 void kvm_mmu_module_exit(void);
 
@@ -986,10 +974,12 @@ u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
 
 /* control of guest tsc rate supported? */
 extern bool kvm_has_tsc_control;
-/* minimum supported tsc_khz for guests */
-extern u32  kvm_min_guest_tsc_khz;
 /* maximum supported tsc_khz for guests */
 extern u32  kvm_max_guest_tsc_khz;
+/* number of bits of the fractional part of the TSC scaling ratio */
+extern u8   kvm_tsc_scaling_ratio_frac_bits;
+/* maximum allowed value of TSC scaling ratio */
+extern u64  kvm_max_tsc_scaling_ratio;
 
 enum emulation_result {
        EMULATE_DONE,         /* no further processing */
@@ -1235,6 +1225,9 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 void kvm_define_shared_msr(unsigned index, u32 msr);
 int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
 
+u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc);
+u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc);
+
 unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu);
 bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
 
index 9f3905697f123200eb1f7ecc749239dc5d5e1b2d..690b4027e17c994fdef4a626f270ca8b97ee041a 100644 (file)
@@ -35,7 +35,7 @@
 #define MSR_IA32_PERFCTR0              0x000000c1
 #define MSR_IA32_PERFCTR1              0x000000c2
 #define MSR_FSB_FREQ                   0x000000cd
-#define MSR_NHM_PLATFORM_INFO          0x000000ce
+#define MSR_PLATFORM_INFO              0x000000ce
 
 #define MSR_NHM_SNB_PKG_CST_CFG_CTL    0x000000e2
 #define NHM_C3_AUTO_DEMOTE             (1UL << 25)
@@ -44,7 +44,6 @@
 #define SNB_C1_AUTO_UNDEMOTE           (1UL << 27)
 #define SNB_C3_AUTO_UNDEMOTE           (1UL << 28)
 
-#define MSR_PLATFORM_INFO              0x000000ce
 #define MSR_MTRRcap                    0x000000fe
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
index aa336ff3e03ec9c0680f7599bb642f807c64b81b..14c63c7e8337a3d2bdfc98a5b4c14d2892de5580 100644 (file)
@@ -73,6 +73,7 @@
 #define SECONDARY_EXEC_ENABLE_PML               0x00020000
 #define SECONDARY_EXEC_XSAVES                  0x00100000
 #define SECONDARY_EXEC_PCOMMIT                 0x00200000
+#define SECONDARY_EXEC_TSC_SCALING              0x02000000
 
 #define PIN_BASED_EXT_INTR_MASK                 0x00000001
 #define PIN_BASED_NMI_EXITING                   0x00000008
@@ -167,6 +168,8 @@ enum vmcs_field {
        VMWRITE_BITMAP                  = 0x00002028,
        XSS_EXIT_BITMAP                 = 0x0000202C,
        XSS_EXIT_BITMAP_HIGH            = 0x0000202D,
+       TSC_MULTIPLIER                  = 0x00002032,
+       TSC_MULTIPLIER_HIGH             = 0x00002033,
        GUEST_PHYSICAL_ADDRESS          = 0x00002400,
        GUEST_PHYSICAL_ADDRESS_HIGH     = 0x00002401,
        VMCS_LINK_POINTER               = 0x00002800,
index b5d7640abc5d6172838a99569d144f8acc96763a..8a4add8e463932445ba071903378927f76912cfa 100644 (file)
        { SVM_EXIT_EXCP_BASE + UD_VECTOR,       "UD excp" }, \
        { SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
        { SVM_EXIT_EXCP_BASE + NM_VECTOR,       "NM excp" }, \
+       { SVM_EXIT_EXCP_BASE + AC_VECTOR,       "AC excp" }, \
        { SVM_EXIT_EXCP_BASE + MC_VECTOR,       "MC excp" }, \
        { SVM_EXIT_INTR,        "interrupt" }, \
        { SVM_EXIT_NMI,         "nmi" }, \
index 836d11b92811ce73446a6081f02a38231fdb9429..861bc59c8f2564eac7b87193e7cd250571e1fbf4 100644 (file)
@@ -361,7 +361,11 @@ int __init arch_probe_nr_irqs(void)
        if (nr < nr_irqs)
                nr_irqs = nr;
 
-       return nr_legacy_irqs();
+       /*
+        * We don't know if PIC is present at this point so we need to do
+        * probe() to get the right number of legacy IRQs.
+        */
+       return legacy_pic->probe();
 }
 
 #ifdef CONFIG_X86_IO_APIC
index 4a70fc6d400adbd1e342f249baec98592a92509d..a8816b3251620c941f543e595e949aa60c43467d 100644 (file)
@@ -352,6 +352,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
        unsigned bits;
        int cpu = smp_processor_id();
+       unsigned int socket_id, core_complex_id;
 
        bits = c->x86_coreid_bits;
        /* Low order bits define the core id (index of core in socket) */
@@ -361,6 +362,18 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
        /* use socket ID also for last level cache */
        per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
        amd_get_topology(c);
+
+       /*
+        * Fix percpu cpu_llc_id here as LLC topology is different
+        * for Fam17h systems.
+        */
+        if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
+               return;
+
+       socket_id       = (c->apicid >> bits) - 1;
+       core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
+
+       per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
 #endif
 }
 
index 4ddd780aeac90ab353134453316dc18108c8b308..c2b7522cbf357617bf8302f3c4f964834b940926 100644 (file)
@@ -273,10 +273,9 @@ __setup("nosmap", setup_disable_smap);
 
 static __always_inline void setup_smap(struct cpuinfo_x86 *c)
 {
-       unsigned long eflags;
+       unsigned long eflags = native_save_fl();
 
        /* This should have been cleared long ago */
-       raw_local_save_flags(eflags);
        BUG_ON(eflags & X86_EFLAGS_AC);
 
        if (cpu_has(c, X86_FEATURE_SMAP)) {
index 98a13db5f4be5826a47c8572f3f7f65950658270..209ac1e7d1f03664010955dea71d953f6a396b5b 100644 (file)
@@ -97,6 +97,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
                switch (c->x86_model) {
                case 0x27:      /* Penwell */
                case 0x35:      /* Cloverview */
+               case 0x4a:      /* Merrifield */
                        set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
                        break;
                default:
index 81431c0f0614cbd3c31b946918e842adb24e5c79..ed446bdcbf312daa9587a593fc1552cda4714dd3 100644 (file)
@@ -107,12 +107,6 @@ static ssize_t __rapl_##_var##_show(struct kobject *kobj,  \
 static struct kobj_attribute format_attr_##_var =              \
        __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
 
-#define RAPL_EVENT_DESC(_name, _config)                                \
-{                                                              \
-       .attr   = __ATTR(_name, 0444, rapl_event_show, NULL),   \
-       .config = _config,                                      \
-}
-
 #define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
 
 #define RAPL_EVENT_ATTR_STR(_name, v, str)                             \
index ef29b742cea79a99c8e653ea91ae83e82b08ba65..31c6a60505e6bc6e5acb84df728d45f73ef701aa 100644 (file)
@@ -385,20 +385,19 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,
  */
 void fpu__init_prepare_fx_sw_frame(void)
 {
-       int fsave_header_size = sizeof(struct fregs_state);
        int size = xstate_size + FP_XSTATE_MAGIC2_SIZE;
 
-       if (config_enabled(CONFIG_X86_32))
-               size += fsave_header_size;
-
        fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
        fx_sw_reserved.extended_size = size;
        fx_sw_reserved.xfeatures = xfeatures_mask;
        fx_sw_reserved.xstate_size = xstate_size;
 
-       if (config_enabled(CONFIG_IA32_EMULATION)) {
+       if (config_enabled(CONFIG_IA32_EMULATION) ||
+           config_enabled(CONFIG_X86_32)) {
+               int fsave_header_size = sizeof(struct fregs_state);
+
                fx_sw_reserved_ia32 = fx_sw_reserved;
-               fx_sw_reserved_ia32.extended_size += fsave_header_size;
+               fx_sw_reserved_ia32.extended_size = size + fsave_header_size;
        }
 }
 
index 6454f2731b5666e49aeda8f87d96078d564de2f2..70fc312221fc6b6c3223673c0328dfdc73c59ea6 100644 (file)
@@ -694,7 +694,6 @@ void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
        if (!boot_cpu_has(X86_FEATURE_XSAVE))
                return NULL;
 
-       xsave = &current->thread.fpu.state.xsave;
        /*
         * We should not ever be requesting features that we
         * have not enabled.  Remember that pcntxt_mask is
index 1d40ca8a73f27231e49c35704794d0cbe6ca94dc..ffdc0e8603902b12b0cd44fd175d806b046ccb4b 100644 (file)
@@ -65,6 +65,9 @@ startup_64:
         * tables and then reload them.
         */
 
+       /* Sanitize CPU configuration */
+       call verify_cpu
+
        /*
         * Compute the delta between the address I am compiled to run at and the
         * address I am actually running at.
@@ -174,6 +177,9 @@ ENTRY(secondary_startup_64)
         * after the boot processor executes this code.
         */
 
+       /* Sanitize CPU configuration */
+       call verify_cpu
+
        movq    $(init_level4_pgt - __START_KERNEL_map), %rax
 1:
 
@@ -288,6 +294,8 @@ ENTRY(secondary_startup_64)
        pushq   %rax            # target address in negative space
        lretq
 
+#include "verify_cpu.S"
+
 #ifdef CONFIG_HOTPLUG_CPU
 /*
  * Boot CPU0 entry point. It's called from play_dead(). Everything has been set
index 16cb827a5b27745d1f571d49a5b45443babb2c8c..be22f5a2192e358153610ebdf95a823da1ea8e5f 100644 (file)
@@ -295,16 +295,11 @@ static void unmask_8259A(void)
        raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-static void init_8259A(int auto_eoi)
+static int probe_8259A(void)
 {
        unsigned long flags;
        unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
        unsigned char new_val;
-
-       i8259A_auto_eoi = auto_eoi;
-
-       raw_spin_lock_irqsave(&i8259A_lock, flags);
-
        /*
         * Check to see if we have a PIC.
         * Mask all except the cascade and read
@@ -312,16 +307,28 @@ static void init_8259A(int auto_eoi)
         * have a PIC, we will read 0xff as opposed to the
         * value we wrote.
         */
+       raw_spin_lock_irqsave(&i8259A_lock, flags);
+
        outb(0xff, PIC_SLAVE_IMR);      /* mask all of 8259A-2 */
        outb(probe_val, PIC_MASTER_IMR);
        new_val = inb(PIC_MASTER_IMR);
        if (new_val != probe_val) {
                printk(KERN_INFO "Using NULL legacy PIC\n");
                legacy_pic = &null_legacy_pic;
-               raw_spin_unlock_irqrestore(&i8259A_lock, flags);
-               return;
        }
 
+       raw_spin_unlock_irqrestore(&i8259A_lock, flags);
+       return nr_legacy_irqs();
+}
+
+static void init_8259A(int auto_eoi)
+{
+       unsigned long flags;
+
+       i8259A_auto_eoi = auto_eoi;
+
+       raw_spin_lock_irqsave(&i8259A_lock, flags);
+
        outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
 
        /*
@@ -379,6 +386,10 @@ static int legacy_pic_irq_pending_noop(unsigned int irq)
 {
        return 0;
 }
+static int legacy_pic_probe(void)
+{
+       return 0;
+}
 
 struct legacy_pic null_legacy_pic = {
        .nr_legacy_irqs = 0,
@@ -388,6 +399,7 @@ struct legacy_pic null_legacy_pic = {
        .mask_all = legacy_pic_noop,
        .restore_mask = legacy_pic_noop,
        .init = legacy_pic_int_noop,
+       .probe = legacy_pic_probe,
        .irq_pending = legacy_pic_irq_pending_noop,
        .make_irq = legacy_pic_uint_noop,
 };
@@ -400,6 +412,7 @@ struct legacy_pic default_legacy_pic = {
        .mask_all = mask_8259A,
        .restore_mask = unmask_8259A,
        .init = init_8259A,
+       .probe = probe_8259A,
        .irq_pending = i8259A_irq_pending,
        .make_irq = make_8259A_irq,
 };
index 94ea120fa21ff7a9de85cc123054e9d2133b2305..87e1762e2bca74a3f22004d09d9069d72b41b62b 100644 (file)
@@ -278,6 +278,12 @@ trace:
        /* save_mcount_regs fills in first two parameters */
        save_mcount_regs
 
+       /*
+        * When DYNAMIC_FTRACE is not defined, ARCH_SUPPORTS_FTRACE_OPS is not
+        * set (see include/asm/ftrace.h and include/linux/ftrace.h).  Only the
+        * ip and parent ip are used and the list function is called when
+        * function tracing is enabled.
+        */
        call   *ftrace_trace_function
 
        restore_mcount_regs
index a1e4da98c8f0db8c838766e9466c2608c124fe98..29db25f9a745ee11d23867cc974438817a6e5b15 100644 (file)
@@ -1188,7 +1188,7 @@ void __init setup_arch(char **cmdline_p)
         */
        clone_pgd_range(initial_page_table,
                        swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
-                       KERNEL_PGD_PTRS);
+                       min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
 #endif
 
        tboot_probe();
index b9242bacbe59a2c02baee2e0d89fe8247b13106b..4cf401f581e7e720f858393476eb895a440d0ab2 100644 (file)
 #include <asm/msr-index.h>
 
 verify_cpu:
-       pushfl                          # Save caller passed flags
-       pushl   $0                      # Kill any dangerous flags
-       popfl
+       pushf                           # Save caller passed flags
+       push    $0                      # Kill any dangerous flags
+       popf
 
+#ifndef __x86_64__
        pushfl                          # standard way to check for cpuid
        popl    %eax
        movl    %eax,%ebx
@@ -48,6 +49,7 @@ verify_cpu:
        popl    %eax
        cmpl    %eax,%ebx
        jz      verify_cpu_no_longmode  # cpu has no cpuid
+#endif
 
        movl    $0x0,%eax               # See if cpuid 1 is implemented
        cpuid
@@ -130,10 +132,10 @@ verify_cpu_sse_test:
        jmp     verify_cpu_sse_test     # try again
 
 verify_cpu_no_longmode:
-       popfl                           # Restore caller passed flags
+       popf                            # Restore caller passed flags
        movl $1,%eax
        ret
 verify_cpu_sse_ok:
-       popfl                           # Restore caller passed flags
+       popf                            # Restore caller passed flags
        xorl %eax, %eax
        ret
index ecd4ea1d28a8ce01b5b693f5b7d8a953e50131a1..4d30b865be30641f4964a3279939020e9f1a057a 100644 (file)
@@ -1250,7 +1250,7 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
 
        tsc_deadline = apic->lapic_timer.expired_tscdeadline;
        apic->lapic_timer.expired_tscdeadline = 0;
-       guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc());
+       guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
        trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline);
 
        /* __delay is delay_tsc whenever the hardware has TSC, thus always.  */
@@ -1318,7 +1318,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
                local_irq_save(flags);
 
                now = apic->lapic_timer.timer.base->get_time();
-               guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, rdtsc());
+               guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
                if (likely(tscdeadline > guest_tsc)) {
                        ns = (tscdeadline - guest_tsc) * 1000000ULL;
                        do_div(ns, this_tsc_khz);
index 7d85bcae3332f0eb04c0fb9314a6c401de271e18..e7c2c1428a691676a6a1fdadee044ab45124acc2 100644 (file)
@@ -3359,7 +3359,7 @@ walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
        return reserved;
 }
 
-int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 {
        u64 spte;
        bool reserved;
@@ -3368,7 +3368,7 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
                return RET_MMIO_PF_EMULATE;
 
        reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte);
-       if (unlikely(reserved))
+       if (WARN_ON(reserved))
                return RET_MMIO_PF_BUG;
 
        if (is_mmio_spte(spte)) {
@@ -3392,17 +3392,7 @@ int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
         */
        return RET_MMIO_PF_RETRY;
 }
-EXPORT_SYMBOL_GPL(handle_mmio_page_fault_common);
-
-static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr,
-                                 u32 error_code, bool direct)
-{
-       int ret;
-
-       ret = handle_mmio_page_fault_common(vcpu, addr, direct);
-       WARN_ON(ret == RET_MMIO_PF_BUG);
-       return ret;
-}
+EXPORT_SYMBOL_GPL(handle_mmio_page_fault);
 
 static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
                                u32 error_code, bool prefault)
@@ -3413,7 +3403,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
        pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
 
        if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, gva, error_code, true);
+               r = handle_mmio_page_fault(vcpu, gva, true);
 
                if (likely(r != RET_MMIO_PF_INVALID))
                        return r;
@@ -3503,7 +3493,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
        MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
        if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, gpa, error_code, true);
+               r = handle_mmio_page_fault(vcpu, gpa, true);
 
                if (likely(r != RET_MMIO_PF_INVALID))
                        return r;
index e4202e41d53541f06a468e0b72beac483e2e7b8f..55ffb7b0f95e9f82a97e8fd4ab7caf4f720fc335 100644 (file)
@@ -56,13 +56,13 @@ void
 reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
 
 /*
- * Return values of handle_mmio_page_fault_common:
+ * Return values of handle_mmio_page_fault:
  * RET_MMIO_PF_EMULATE: it is a real mmio page fault, emulate the instruction
  *                     directly.
  * RET_MMIO_PF_INVALID: invalid spte is detected then let the real page
  *                     fault path update the mmio spte.
  * RET_MMIO_PF_RETRY: let CPU fault again on the address.
- * RET_MMIO_PF_BUG: bug is detected.
+ * RET_MMIO_PF_BUG: a bug was detected (and a WARN was printed).
  */
 enum {
        RET_MMIO_PF_EMULATE = 1,
@@ -71,7 +71,7 @@ enum {
        RET_MMIO_PF_BUG = -1
 };
 
-int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
+int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct);
 void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
 void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly);
 
index b41faa91a6f97ef4342b1c671160ddc5311b8502..3058a22a658d25db2bb8ecf4a37657bc1f873c1d 100644 (file)
@@ -705,8 +705,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
        pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
 
        if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, addr, error_code,
-                                             mmu_is_nested(vcpu));
+               r = handle_mmio_page_fault(vcpu, addr, mmu_is_nested(vcpu));
                if (likely(r != RET_MMIO_PF_INVALID))
                        return r;
 
index f2c8e4917688a34a9dfb3994d776e8efab512fc2..83a1c643f9a50fd3fa0ffc041c40d9f4d25aa5b5 100644 (file)
@@ -158,8 +158,6 @@ struct vcpu_svm {
        unsigned long int3_rip;
        u32 apf_reason;
 
-       u64  tsc_ratio;
-
        /* cached guest cpuid flags for faster access */
        bool nrips_enabled      : 1;
 };
@@ -214,7 +212,6 @@ static int nested_svm_intercept(struct vcpu_svm *svm);
 static int nested_svm_vmexit(struct vcpu_svm *svm);
 static int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr,
                                      bool has_error_code, u32 error_code);
-static u64 __scale_tsc(u64 ratio, u64 tsc);
 
 enum {
        VMCB_INTERCEPTS, /* Intercept vectors, TSC offset,
@@ -894,20 +891,9 @@ static __init int svm_hardware_setup(void)
                kvm_enable_efer_bits(EFER_FFXSR);
 
        if (boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
-               u64 max;
-
                kvm_has_tsc_control = true;
-
-               /*
-                * Make sure the user can only configure tsc_khz values that
-                * fit into a signed integer.
-                * A min value is not calculated needed because it will always
-                * be 1 on all machines and a value of 0 is used to disable
-                * tsc-scaling for the vcpu.
-                */
-               max = min(0x7fffffffULL, __scale_tsc(tsc_khz, TSC_RATIO_MAX));
-
-               kvm_max_guest_tsc_khz = max;
+               kvm_max_tsc_scaling_ratio = TSC_RATIO_MAX;
+               kvm_tsc_scaling_ratio_frac_bits = 32;
        }
 
        if (nested) {
@@ -971,68 +957,6 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
        seg->base = 0;
 }
 
-static u64 __scale_tsc(u64 ratio, u64 tsc)
-{
-       u64 mult, frac, _tsc;
-
-       mult  = ratio >> 32;
-       frac  = ratio & ((1ULL << 32) - 1);
-
-       _tsc  = tsc;
-       _tsc *= mult;
-       _tsc += (tsc >> 32) * frac;
-       _tsc += ((tsc & ((1ULL << 32) - 1)) * frac) >> 32;
-
-       return _tsc;
-}
-
-static u64 svm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-       u64 _tsc = tsc;
-
-       if (svm->tsc_ratio != TSC_RATIO_DEFAULT)
-               _tsc = __scale_tsc(svm->tsc_ratio, tsc);
-
-       return _tsc;
-}
-
-static void svm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
-{
-       struct vcpu_svm *svm = to_svm(vcpu);
-       u64 ratio;
-       u64 khz;
-
-       /* Guest TSC same frequency as host TSC? */
-       if (!scale) {
-               svm->tsc_ratio = TSC_RATIO_DEFAULT;
-               return;
-       }
-
-       /* TSC scaling supported? */
-       if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
-               if (user_tsc_khz > tsc_khz) {
-                       vcpu->arch.tsc_catchup = 1;
-                       vcpu->arch.tsc_always_catchup = 1;
-               } else
-                       WARN(1, "user requested TSC rate below hardware speed\n");
-               return;
-       }
-
-       khz = user_tsc_khz;
-
-       /* TSC scaling required  - calculate ratio */
-       ratio = khz << 32;
-       do_div(ratio, tsc_khz);
-
-       if (ratio == 0 || ratio & TSC_RATIO_RSVD) {
-               WARN_ONCE(1, "Invalid TSC ratio - virtual-tsc-khz=%u\n",
-                               user_tsc_khz);
-               return;
-       }
-       svm->tsc_ratio             = ratio;
-}
-
 static u64 svm_read_tsc_offset(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -1059,16 +983,10 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
-static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
+static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
-       if (host) {
-               if (svm->tsc_ratio != TSC_RATIO_DEFAULT)
-                       WARN_ON(adjustment < 0);
-               adjustment = svm_scale_tsc(vcpu, (u64)adjustment);
-       }
-
        svm->vmcb->control.tsc_offset += adjustment;
        if (is_guest_mode(vcpu))
                svm->nested.hsave->control.tsc_offset += adjustment;
@@ -1080,15 +998,6 @@ static void svm_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
        mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
-static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
-{
-       u64 tsc;
-
-       tsc = svm_scale_tsc(vcpu, rdtsc());
-
-       return target_tsc - tsc;
-}
-
 static void init_vmcb(struct vcpu_svm *svm)
 {
        struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1110,6 +1019,8 @@ static void init_vmcb(struct vcpu_svm *svm)
        set_exception_intercept(svm, PF_VECTOR);
        set_exception_intercept(svm, UD_VECTOR);
        set_exception_intercept(svm, MC_VECTOR);
+       set_exception_intercept(svm, AC_VECTOR);
+       set_exception_intercept(svm, DB_VECTOR);
 
        set_intercept(svm, INTERCEPT_INTR);
        set_intercept(svm, INTERCEPT_NMI);
@@ -1235,8 +1146,6 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
                goto out;
        }
 
-       svm->tsc_ratio = TSC_RATIO_DEFAULT;
-
        err = kvm_vcpu_init(&svm->vcpu, kvm, id);
        if (err)
                goto free_svm;
@@ -1322,10 +1231,12 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
                rdmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 
-       if (static_cpu_has(X86_FEATURE_TSCRATEMSR) &&
-           svm->tsc_ratio != __this_cpu_read(current_tsc_ratio)) {
-               __this_cpu_write(current_tsc_ratio, svm->tsc_ratio);
-               wrmsrl(MSR_AMD64_TSC_RATIO, svm->tsc_ratio);
+       if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
+               u64 tsc_ratio = vcpu->arch.tsc_scaling_ratio;
+               if (tsc_ratio != __this_cpu_read(current_tsc_ratio)) {
+                       __this_cpu_write(current_tsc_ratio, tsc_ratio);
+                       wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio);
+               }
        }
 }
 
@@ -1644,20 +1555,13 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
        mark_dirty(svm->vmcb, VMCB_SEG);
 }
 
-static void update_db_bp_intercept(struct kvm_vcpu *vcpu)
+static void update_bp_intercept(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
-       clr_exception_intercept(svm, DB_VECTOR);
        clr_exception_intercept(svm, BP_VECTOR);
 
-       if (svm->nmi_singlestep)
-               set_exception_intercept(svm, DB_VECTOR);
-
        if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
-               if (vcpu->guest_debug &
-                   (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
-                       set_exception_intercept(svm, DB_VECTOR);
                if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
                        set_exception_intercept(svm, BP_VECTOR);
        } else
@@ -1763,7 +1667,6 @@ static int db_interception(struct vcpu_svm *svm)
                if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
                        svm->vmcb->save.rflags &=
                                ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
-               update_db_bp_intercept(&svm->vcpu);
        }
 
        if (svm->vcpu.guest_debug &
@@ -1798,6 +1701,12 @@ static int ud_interception(struct vcpu_svm *svm)
        return 1;
 }
 
+static int ac_interception(struct vcpu_svm *svm)
+{
+       kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
+       return 1;
+}
+
 static void svm_fpu_activate(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -3075,8 +2984,7 @@ static int cr8_write_interception(struct vcpu_svm *svm)
 static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
 {
        struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
-       return vmcb->control.tsc_offset +
-               svm_scale_tsc(vcpu, host_tsc);
+       return vmcb->control.tsc_offset + host_tsc;
 }
 
 static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
@@ -3086,7 +2994,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        switch (msr_info->index) {
        case MSR_IA32_TSC: {
                msr_info->data = svm->vmcb->control.tsc_offset +
-                       svm_scale_tsc(vcpu, rdtsc());
+                       kvm_scale_tsc(vcpu, rdtsc());
 
                break;
        }
@@ -3362,6 +3270,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
        [SVM_EXIT_EXCP_BASE + PF_VECTOR]        = pf_interception,
        [SVM_EXIT_EXCP_BASE + NM_VECTOR]        = nm_interception,
        [SVM_EXIT_EXCP_BASE + MC_VECTOR]        = mc_interception,
+       [SVM_EXIT_EXCP_BASE + AC_VECTOR]        = ac_interception,
        [SVM_EXIT_INTR]                         = intr_interception,
        [SVM_EXIT_NMI]                          = nmi_interception,
        [SVM_EXIT_SMI]                          = nop_on_interception,
@@ -3745,7 +3654,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu)
         */
        svm->nmi_singlestep = true;
        svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
-       update_db_bp_intercept(vcpu);
 }
 
 static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -4371,7 +4279,7 @@ static struct kvm_x86_ops svm_x86_ops = {
        .vcpu_load = svm_vcpu_load,
        .vcpu_put = svm_vcpu_put,
 
-       .update_db_bp_intercept = update_db_bp_intercept,
+       .update_bp_intercept = update_bp_intercept,
        .get_msr = svm_get_msr,
        .set_msr = svm_set_msr,
        .get_segment_base = svm_get_segment_base,
@@ -4443,11 +4351,9 @@ static struct kvm_x86_ops svm_x86_ops = {
 
        .has_wbinvd_exit = svm_has_wbinvd_exit,
 
-       .set_tsc_khz = svm_set_tsc_khz,
        .read_tsc_offset = svm_read_tsc_offset,
        .write_tsc_offset = svm_write_tsc_offset,
-       .adjust_tsc_offset = svm_adjust_tsc_offset,
-       .compute_tsc_offset = svm_compute_tsc_offset,
+       .adjust_tsc_offset_guest = svm_adjust_tsc_offset_guest,
        .read_l1_tsc = svm_read_l1_tsc,
 
        .set_tdp_cr3 = set_tdp_cr3,
index 5eb56ed77c1fdea01652acf0da476761cf7a9aaa..af823a388c1994ba244e3ef0098f1a578408101e 100644 (file)
@@ -107,6 +107,8 @@ static u64 __read_mostly host_xss;
 static bool __read_mostly enable_pml = 1;
 module_param_named(pml, enable_pml, bool, S_IRUGO);
 
+#define KVM_VMX_TSC_MULTIPLIER_MAX     0xffffffffffffffffULL
+
 #define KVM_GUEST_CR0_MASK (X86_CR0_NW | X86_CR0_CD)
 #define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST (X86_CR0_WP | X86_CR0_NE)
 #define KVM_VM_CR0_ALWAYS_ON                                           \
@@ -1172,6 +1174,12 @@ static inline bool cpu_has_vmx_pml(void)
        return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
 }
 
+static inline bool cpu_has_vmx_tsc_scaling(void)
+{
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_TSC_SCALING;
+}
+
 static inline bool report_flexpriority(void)
 {
        return flexpriority_enabled;
@@ -1631,7 +1639,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        u32 eb;
 
        eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
-            (1u << NM_VECTOR) | (1u << DB_VECTOR);
+            (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR);
        if ((vcpu->guest_debug &
             (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
            (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
@@ -2053,6 +2061,12 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
                rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
                vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
+
+               /* Setup TSC multiplier */
+               if (cpu_has_vmx_tsc_scaling())
+                       vmcs_write64(TSC_MULTIPLIER,
+                                    vcpu->arch.tsc_scaling_ratio);
+
                vmx->loaded_vmcs->cpu = cpu;
        }
 
@@ -2357,15 +2371,16 @@ static void setup_msrs(struct vcpu_vmx *vmx)
 
 /*
  * reads and returns guest's timestamp counter "register"
- * guest_tsc = host_tsc + tsc_offset    -- 21.3
+ * guest_tsc = (host_tsc * tsc multiplier) >> 48 + tsc_offset
+ * -- Intel TSC Scaling for Virtualization White Paper, sec 1.3
  */
-static u64 guest_read_tsc(void)
+static u64 guest_read_tsc(struct kvm_vcpu *vcpu)
 {
        u64 host_tsc, tsc_offset;
 
        host_tsc = rdtsc();
        tsc_offset = vmcs_read64(TSC_OFFSET);
-       return host_tsc + tsc_offset;
+       return kvm_scale_tsc(vcpu, host_tsc) + tsc_offset;
 }
 
 /*
@@ -2382,22 +2397,6 @@ static u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
        return host_tsc + tsc_offset;
 }
 
-/*
- * Engage any workarounds for mis-matched TSC rates.  Currently limited to
- * software catchup for faster rates on slower CPUs.
- */
-static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
-{
-       if (!scale)
-               return;
-
-       if (user_tsc_khz > tsc_khz) {
-               vcpu->arch.tsc_catchup = 1;
-               vcpu->arch.tsc_always_catchup = 1;
-       } else
-               WARN(1, "user requested TSC rate below hardware speed\n");
-}
-
 static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu)
 {
        return vmcs_read64(TSC_OFFSET);
@@ -2429,7 +2428,7 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        }
 }
 
-static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
+static void vmx_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
 {
        u64 offset = vmcs_read64(TSC_OFFSET);
 
@@ -2442,11 +2441,6 @@ static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool ho
                                           offset + adjustment);
 }
 
-static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
-{
-       return target_tsc - rdtsc();
-}
-
 static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0);
@@ -2778,7 +2772,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_EFER:
                return kvm_get_msr_common(vcpu, msr_info);
        case MSR_IA32_TSC:
-               msr_info->data = guest_read_tsc();
+               msr_info->data = guest_read_tsc(vcpu);
                break;
        case MSR_IA32_SYSENTER_CS:
                msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
@@ -3154,7 +3148,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                        SECONDARY_EXEC_SHADOW_VMCS |
                        SECONDARY_EXEC_XSAVES |
                        SECONDARY_EXEC_ENABLE_PML |
-                       SECONDARY_EXEC_PCOMMIT;
+                       SECONDARY_EXEC_PCOMMIT |
+                       SECONDARY_EXEC_TSC_SCALING;
                if (adjust_vmx_controls(min2, opt2,
                                        MSR_IA32_VMX_PROCBASED_CTLS2,
                                        &_cpu_based_2nd_exec_control) < 0)
@@ -5266,6 +5261,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
                return handle_rmode_exception(vcpu, ex_no, error_code);
 
        switch (ex_no) {
+       case AC_VECTOR:
+               kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
+               return 1;
        case DB_VECTOR:
                dr6 = vmcs_readl(EXIT_QUALIFICATION);
                if (!(vcpu->guest_debug &
@@ -5908,7 +5906,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
                return 1;
        }
 
-       ret = handle_mmio_page_fault_common(vcpu, gpa, true);
+       ret = handle_mmio_page_fault(vcpu, gpa, true);
        if (likely(ret == RET_MMIO_PF_EMULATE))
                return x86_emulate_instruction(vcpu, gpa, 0, NULL, 0) ==
                                              EMULATE_DONE;
@@ -6199,6 +6197,12 @@ static __init int hardware_setup(void)
        if (!cpu_has_vmx_apicv())
                enable_apicv = 0;
 
+       if (cpu_has_vmx_tsc_scaling()) {
+               kvm_has_tsc_control = true;
+               kvm_max_tsc_scaling_ratio = KVM_VMX_TSC_MULTIPLIER_MAX;
+               kvm_tsc_scaling_ratio_frac_bits = 48;
+       }
+
        if (enable_apicv)
                kvm_x86_ops->update_cr8_intercept = NULL;
        else {
@@ -7390,11 +7394,6 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
 
        switch (type) {
        case VMX_VPID_EXTENT_ALL_CONTEXT:
-               if (get_vmcs12(vcpu)->virtual_processor_id == 0) {
-                       nested_vmx_failValid(vcpu,
-                               VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
-                       return 1;
-               }
                __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
                nested_vmx_succeed(vcpu);
                break;
@@ -8008,6 +8007,9 @@ static void dump_vmcs(void)
               vmcs_read32(IDT_VECTORING_INFO_FIELD),
               vmcs_read32(IDT_VECTORING_ERROR_CODE));
        pr_err("TSC Offset = 0x%016lx\n", vmcs_readl(TSC_OFFSET));
+       if (secondary_exec_control & SECONDARY_EXEC_TSC_SCALING)
+               pr_err("TSC Multiplier = 0x%016lx\n",
+                      vmcs_readl(TSC_MULTIPLIER));
        if (cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW)
                pr_err("TPR Threshold = 0x%02x\n", vmcs_read32(TPR_THRESHOLD));
        if (pin_based_exec_ctrl & PIN_BASED_POSTED_INTR)
@@ -10752,7 +10754,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
        .vcpu_load = vmx_vcpu_load,
        .vcpu_put = vmx_vcpu_put,
 
-       .update_db_bp_intercept = update_exception_bitmap,
+       .update_bp_intercept = update_exception_bitmap,
        .get_msr = vmx_get_msr,
        .set_msr = vmx_set_msr,
        .get_segment_base = vmx_get_segment_base,
@@ -10826,11 +10828,9 @@ static struct kvm_x86_ops vmx_x86_ops = {
 
        .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
 
-       .set_tsc_khz = vmx_set_tsc_khz,
        .read_tsc_offset = vmx_read_tsc_offset,
        .write_tsc_offset = vmx_write_tsc_offset,
-       .adjust_tsc_offset = vmx_adjust_tsc_offset,
-       .compute_tsc_offset = vmx_compute_tsc_offset,
+       .adjust_tsc_offset_guest = vmx_adjust_tsc_offset_guest,
        .read_l1_tsc = vmx_read_l1_tsc,
 
        .set_tdp_cr3 = vmx_set_cr3,
index 4a6eff166fc61fa2053141f410260f2667f8a965..eed32283d22cc0cafbff75e8f2a246887d4cbb5f 100644 (file)
@@ -93,10 +93,10 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu);
 static void process_nmi(struct kvm_vcpu *vcpu);
 static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
 
-struct kvm_x86_ops *kvm_x86_ops;
+struct kvm_x86_ops *kvm_x86_ops __read_mostly;
 EXPORT_SYMBOL_GPL(kvm_x86_ops);
 
-static bool ignore_msrs = 0;
+static bool __read_mostly ignore_msrs = 0;
 module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR);
 
 unsigned int min_timer_period_us = 500;
@@ -105,20 +105,25 @@ module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
 static bool __read_mostly kvmclock_periodic_sync = true;
 module_param(kvmclock_periodic_sync, bool, S_IRUGO);
 
-bool kvm_has_tsc_control;
+bool __read_mostly kvm_has_tsc_control;
 EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
-u32  kvm_max_guest_tsc_khz;
+u32  __read_mostly kvm_max_guest_tsc_khz;
 EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
+u8   __read_mostly kvm_tsc_scaling_ratio_frac_bits;
+EXPORT_SYMBOL_GPL(kvm_tsc_scaling_ratio_frac_bits);
+u64  __read_mostly kvm_max_tsc_scaling_ratio;
+EXPORT_SYMBOL_GPL(kvm_max_tsc_scaling_ratio);
+static u64 __read_mostly kvm_default_tsc_scaling_ratio;
 
 /* tsc tolerance in parts per million - default to 1/2 of the NTP threshold */
-static u32 tsc_tolerance_ppm = 250;
+static u32 __read_mostly tsc_tolerance_ppm = 250;
 module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
 
 /* lapic timer advance (tscdeadline mode only) in nanoseconds */
-unsigned int lapic_timer_advance_ns = 0;
+unsigned int __read_mostly lapic_timer_advance_ns = 0;
 module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
 
-static bool backwards_tsc_observed = false;
+static bool __read_mostly backwards_tsc_observed = false;
 
 #define KVM_NR_SHARED_MSRS 16
 
@@ -1249,14 +1254,53 @@ static u32 adjust_tsc_khz(u32 khz, s32 ppm)
        return v;
 }
 
-static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
+static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
+{
+       u64 ratio;
+
+       /* Guest TSC same frequency as host TSC? */
+       if (!scale) {
+               vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
+               return 0;
+       }
+
+       /* TSC scaling supported? */
+       if (!kvm_has_tsc_control) {
+               if (user_tsc_khz > tsc_khz) {
+                       vcpu->arch.tsc_catchup = 1;
+                       vcpu->arch.tsc_always_catchup = 1;
+                       return 0;
+               } else {
+                       WARN(1, "user requested TSC rate below hardware speed\n");
+                       return -1;
+               }
+       }
+
+       /* TSC scaling required  - calculate ratio */
+       ratio = mul_u64_u32_div(1ULL << kvm_tsc_scaling_ratio_frac_bits,
+                               user_tsc_khz, tsc_khz);
+
+       if (ratio == 0 || ratio >= kvm_max_tsc_scaling_ratio) {
+               WARN_ONCE(1, "Invalid TSC scaling ratio - virtual-tsc-khz=%u\n",
+                         user_tsc_khz);
+               return -1;
+       }
+
+       vcpu->arch.tsc_scaling_ratio = ratio;
+       return 0;
+}
+
+static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
 {
        u32 thresh_lo, thresh_hi;
        int use_scaling = 0;
 
        /* tsc_khz can be zero if TSC calibration fails */
-       if (this_tsc_khz == 0)
-               return;
+       if (this_tsc_khz == 0) {
+               /* set tsc_scaling_ratio to a safe value */
+               vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
+               return -1;
+       }
 
        /* Compute a scale to convert nanoseconds in TSC cycles */
        kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
@@ -1276,7 +1320,7 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
                pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", this_tsc_khz, thresh_lo, thresh_hi);
                use_scaling = 1;
        }
-       kvm_x86_ops->set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
+       return set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
 }
 
 static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
@@ -1322,6 +1366,48 @@ static void update_ia32_tsc_adjust_msr(struct kvm_vcpu *vcpu, s64 offset)
        vcpu->arch.ia32_tsc_adjust_msr += offset - curr_offset;
 }
 
+/*
+ * Multiply tsc by a fixed point number represented by ratio.
+ *
+ * The most significant 64-N bits (mult) of ratio represent the
+ * integral part of the fixed point number; the remaining N bits
+ * (frac) represent the fractional part, ie. ratio represents a fixed
+ * point number (mult + frac * 2^(-N)).
+ *
+ * N equals to kvm_tsc_scaling_ratio_frac_bits.
+ */
+static inline u64 __scale_tsc(u64 ratio, u64 tsc)
+{
+       return mul_u64_u64_shr(tsc, ratio, kvm_tsc_scaling_ratio_frac_bits);
+}
+
+u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc)
+{
+       u64 _tsc = tsc;
+       u64 ratio = vcpu->arch.tsc_scaling_ratio;
+
+       if (ratio != kvm_default_tsc_scaling_ratio)
+               _tsc = __scale_tsc(ratio, tsc);
+
+       return _tsc;
+}
+EXPORT_SYMBOL_GPL(kvm_scale_tsc);
+
+static u64 kvm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
+{
+       u64 tsc;
+
+       tsc = kvm_scale_tsc(vcpu, rdtsc());
+
+       return target_tsc - tsc;
+}
+
+u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
+{
+       return kvm_x86_ops->read_l1_tsc(vcpu, kvm_scale_tsc(vcpu, host_tsc));
+}
+EXPORT_SYMBOL_GPL(kvm_read_l1_tsc);
+
 void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
        struct kvm *kvm = vcpu->kvm;
@@ -1333,7 +1419,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
        u64 data = msr->data;
 
        raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
-       offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
+       offset = kvm_compute_tsc_offset(vcpu, data);
        ns = get_kernel_ns();
        elapsed = ns - kvm->arch.last_tsc_nsec;
 
@@ -1390,7 +1476,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
                } else {
                        u64 delta = nsec_to_cycles(vcpu, elapsed);
                        data += delta;
-                       offset = kvm_x86_ops->compute_tsc_offset(vcpu, data);
+                       offset = kvm_compute_tsc_offset(vcpu, data);
                        pr_debug("kvm: adjusted tsc offset by %llu\n", delta);
                }
                matched = true;
@@ -1447,6 +1533,20 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
 
 EXPORT_SYMBOL_GPL(kvm_write_tsc);
 
+static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
+                                          s64 adjustment)
+{
+       kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment);
+}
+
+static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
+{
+       if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio)
+               WARN_ON(adjustment < 0);
+       adjustment = kvm_scale_tsc(vcpu, (u64) adjustment);
+       kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment);
+}
+
 #ifdef CONFIG_X86_64
 
 static cycle_t read_tsc(void)
@@ -1608,7 +1708,7 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 
 static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
-       unsigned long flags, this_tsc_khz;
+       unsigned long flags, this_tsc_khz, tgt_tsc_khz;
        struct kvm_vcpu_arch *vcpu = &v->arch;
        struct kvm_arch *ka = &v->kvm->arch;
        s64 kernel_ns;
@@ -1645,7 +1745,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                kernel_ns = get_kernel_ns();
        }
 
-       tsc_timestamp = kvm_x86_ops->read_l1_tsc(v, host_tsc);
+       tsc_timestamp = kvm_read_l1_tsc(v, host_tsc);
 
        /*
         * We may have to catch up the TSC to match elapsed wall clock
@@ -1671,7 +1771,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                return 0;
 
        if (unlikely(vcpu->hw_tsc_khz != this_tsc_khz)) {
-               kvm_get_time_scale(NSEC_PER_SEC / 1000, this_tsc_khz,
+               tgt_tsc_khz = kvm_has_tsc_control ?
+                       vcpu->virtual_tsc_khz : this_tsc_khz;
+               kvm_get_time_scale(NSEC_PER_SEC / 1000, tgt_tsc_khz,
                                   &vcpu->hv_clock.tsc_shift,
                                   &vcpu->hv_clock.tsc_to_system_mul);
                vcpu->hw_tsc_khz = this_tsc_khz;
@@ -2617,7 +2719,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                if (tsc_delta < 0)
                        mark_tsc_unstable("KVM discovered backwards TSC");
                if (check_tsc_unstable()) {
-                       u64 offset = kvm_x86_ops->compute_tsc_offset(vcpu,
+                       u64 offset = kvm_compute_tsc_offset(vcpu,
                                                vcpu->arch.last_guest_tsc);
                        kvm_x86_ops->write_tsc_offset(vcpu, offset);
                        vcpu->arch.tsc_catchup = 1;
@@ -2661,6 +2763,26 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu)
+{
+       return (!lapic_in_kernel(vcpu) ||
+               kvm_apic_accept_pic_intr(vcpu));
+}
+
+/*
+ * if userspace requested an interrupt window, check that the
+ * interrupt window is open.
+ *
+ * No need to exit to userspace if we already have an interrupt queued.
+ */
+static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu)
+{
+       return kvm_arch_interrupt_allowed(vcpu) &&
+               !kvm_cpu_has_interrupt(vcpu) &&
+               !kvm_event_needs_reinjection(vcpu) &&
+               kvm_cpu_accept_dm_intr(vcpu);
+}
+
 static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
                                    struct kvm_interrupt *irq)
 {
@@ -2684,6 +2806,7 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
                return -EEXIST;
 
        vcpu->arch.pending_external_vector = irq->irq;
+       kvm_make_request(KVM_REQ_EVENT, vcpu);
        return 0;
 }
 
@@ -3319,9 +3442,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                if (user_tsc_khz == 0)
                        user_tsc_khz = tsc_khz;
 
-               kvm_set_tsc_khz(vcpu, user_tsc_khz);
+               if (!kvm_set_tsc_khz(vcpu, user_tsc_khz))
+                       r = 0;
 
-               r = 0;
                goto out;
        }
        case KVM_GET_TSC_KHZ: {
@@ -5808,23 +5931,10 @@ static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
        return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
 }
 
-/*
- * Check if userspace requested an interrupt window, and that the
- * interrupt window is open.
- *
- * No need to exit to userspace if we already have an interrupt queued.
- */
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
 {
-       if (!vcpu->run->request_interrupt_window || pic_in_kernel(vcpu->kvm))
-               return false;
-
-       if (kvm_cpu_has_interrupt(vcpu))
-               return false;
-
-       return (irqchip_split(vcpu->kvm)
-               ? kvm_apic_accept_pic_intr(vcpu)
-               : kvm_arch_interrupt_allowed(vcpu));
+       return vcpu->run->request_interrupt_window &&
+               likely(!pic_in_kernel(vcpu->kvm));
 }
 
 static void post_kvm_run_save(struct kvm_vcpu *vcpu)
@@ -5835,17 +5945,9 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
        kvm_run->flags = is_smm(vcpu) ? KVM_RUN_X86_SMM : 0;
        kvm_run->cr8 = kvm_get_cr8(vcpu);
        kvm_run->apic_base = kvm_get_apic_base(vcpu);
-       if (!irqchip_in_kernel(vcpu->kvm))
-               kvm_run->ready_for_interrupt_injection =
-                       kvm_arch_interrupt_allowed(vcpu) &&
-                       !kvm_cpu_has_interrupt(vcpu) &&
-                       !kvm_event_needs_reinjection(vcpu);
-       else if (!pic_in_kernel(vcpu->kvm))
-               kvm_run->ready_for_interrupt_injection =
-                       kvm_apic_accept_pic_intr(vcpu) &&
-                       !kvm_cpu_has_interrupt(vcpu);
-       else
-               kvm_run->ready_for_interrupt_injection = 1;
+       kvm_run->ready_for_interrupt_injection =
+               pic_in_kernel(vcpu->kvm) ||
+               kvm_vcpu_ready_for_interrupt_injection(vcpu);
 }
 
 static void update_cr8_intercept(struct kvm_vcpu *vcpu)
@@ -6258,8 +6360,10 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
 static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 {
        int r;
-       bool req_int_win = !lapic_in_kernel(vcpu) &&
-               vcpu->run->request_interrupt_window;
+       bool req_int_win =
+               dm_request_for_irq_injection(vcpu) &&
+               kvm_cpu_accept_dm_intr(vcpu);
+
        bool req_immediate_exit = false;
 
        if (vcpu->requests) {
@@ -6452,8 +6556,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        if (hw_breakpoint_active())
                hw_breakpoint_restore();
 
-       vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu,
-                                                          rdtsc());
+       vcpu->arch.last_guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 
        vcpu->mode = OUTSIDE_GUEST_MODE;
        smp_wmb();
@@ -6562,7 +6665,8 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
                if (kvm_cpu_has_pending_timer(vcpu))
                        kvm_inject_pending_timer_irqs(vcpu);
 
-               if (dm_request_for_irq_injection(vcpu)) {
+               if (dm_request_for_irq_injection(vcpu) &&
+                       kvm_vcpu_ready_for_interrupt_injection(vcpu)) {
                        r = 0;
                        vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
                        ++vcpu->stat.request_irq_exits;
@@ -7015,7 +7119,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
         */
        kvm_set_rflags(vcpu, rflags);
 
-       kvm_x86_ops->update_db_bp_intercept(vcpu);
+       kvm_x86_ops->update_bp_intercept(vcpu);
 
        r = 0;
 
@@ -7364,6 +7468,20 @@ int kvm_arch_hardware_setup(void)
        if (r != 0)
                return r;
 
+       if (kvm_has_tsc_control) {
+               /*
+                * Make sure the user can only configure tsc_khz values that
+                * fit into a signed integer.
+                * A min value is not calculated needed because it will always
+                * be 1 on all machines.
+                */
+               u64 max = min(0x7fffffffULL,
+                             __scale_tsc(kvm_max_tsc_scaling_ratio, tsc_khz));
+               kvm_max_guest_tsc_khz = max;
+
+               kvm_default_tsc_scaling_ratio = 1ULL << kvm_tsc_scaling_ratio_frac_bits;
+       }
+
        kvm_init_msr_list();
        return 0;
 }
index 1bf417e9cc1309e3353f08fee9dad6915fb34c0c..a035c2aa780190c8c198e1bd8c2bec20a18d8ecb 100644 (file)
@@ -358,6 +358,21 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
 #define pgd_none(a)  pud_none(__pud(pgd_val(a)))
 #endif
 
+#ifdef CONFIG_X86_64
+static inline bool is_hypervisor_range(int idx)
+{
+       /*
+        * ffff800000000000 - ffff87ffffffffff is reserved for
+        * the hypervisor.
+        */
+       return paravirt_enabled() &&
+               (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
+               (idx < pgd_index(__PAGE_OFFSET));
+}
+#else
+static inline bool is_hypervisor_range(int idx) { return false; }
+#endif
+
 static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
                                       bool checkwx)
 {
@@ -381,7 +396,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
 
        for (i = 0; i < PTRS_PER_PGD; i++) {
                st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
-               if (!pgd_none(*start)) {
+               if (!pgd_none(*start) && !is_hypervisor_range(i)) {
                        if (pgd_large(*start) || !pgd_present(*start)) {
                                prot = pgd_flags(*start);
                                note_page(m, &st, __pgprot(prot), 1);
index b0ae85f90f10acecc2898e7d19d06ddb6196db57..1202d5ca2fb582d1a71cad1c85f65b61b907c441 100644 (file)
@@ -585,6 +585,29 @@ static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm,
        return bt_addr;
 }
 
+/*
+ * We only want to do a 4-byte get_user() on 32-bit.  Otherwise,
+ * we might run off the end of the bounds table if we are on
+ * a 64-bit kernel and try to get 8 bytes.
+ */
+int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
+               long __user *bd_entry_ptr)
+{
+       u32 bd_entry_32;
+       int ret;
+
+       if (is_64bit_mm(mm))
+               return get_user(*bd_entry_ret, bd_entry_ptr);
+
+       /*
+        * Note that get_user() uses the type of the *pointer* to
+        * establish the size of the get, not the destination.
+        */
+       ret = get_user(bd_entry_32, (u32 __user *)bd_entry_ptr);
+       *bd_entry_ret = bd_entry_32;
+       return ret;
+}
+
 /*
  * Get the base of bounds tables pointed by specific bounds
  * directory entry.
@@ -605,7 +628,7 @@ static int get_bt_addr(struct mm_struct *mm,
                int need_write = 0;
 
                pagefault_disable();
-               ret = get_user(bd_entry, bd_entry_ptr);
+               ret = get_user_bd_entry(mm, &bd_entry, bd_entry_ptr);
                pagefault_enable();
                if (!ret)
                        break;
@@ -700,11 +723,23 @@ static unsigned long mpx_get_bt_entry_offset_bytes(struct mm_struct *mm,
  */
 static inline unsigned long bd_entry_virt_space(struct mm_struct *mm)
 {
-       unsigned long long virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
-       if (is_64bit_mm(mm))
-               return virt_space / MPX_BD_NR_ENTRIES_64;
-       else
-               return virt_space / MPX_BD_NR_ENTRIES_32;
+       unsigned long long virt_space;
+       unsigned long long GB = (1ULL << 30);
+
+       /*
+        * This covers 32-bit emulation as well as 32-bit kernels
+        * running on 64-bit harware.
+        */
+       if (!is_64bit_mm(mm))
+               return (4ULL * GB) / MPX_BD_NR_ENTRIES_32;
+
+       /*
+        * 'x86_virt_bits' returns what the hardware is capable
+        * of, and returns the full >32-bit adddress space when
+        * running 32-bit kernels on 64-bit hardware.
+        */
+       virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
+       return virt_space / MPX_BD_NR_ENTRIES_64;
 }
 
 /*
index 2bbf08cd29007a8da2db6e9cca053c79094ee504..5131993b23a1a2b35670adcbd4ab7d569a29a3d2 100644 (file)
@@ -1575,6 +1575,9 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req,
  * @q: request_queue new bio is being queued at
  * @bio: new bio being queued
  * @request_count: out parameter for number of traversed plugged requests
+ * @same_queue_rq: pointer to &struct request that gets filled in when
+ * another request associated with @q is found on the plug list
+ * (optional, may be %NULL)
  *
  * Determine whether @bio being queued on @q can be merged with a request
  * on %current's plugged list.  Returns %true if merge was successful,
index de5716d8e525969e7849767a775aabec9e4d8b96..41a55ba0d78e8a97b5707a9194cce3b6ebd1c811 100644 (file)
@@ -76,6 +76,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
        struct bio_vec bv, bvprv, *bvprvp = NULL;
        struct bvec_iter iter;
        unsigned seg_size = 0, nsegs = 0, sectors = 0;
+       unsigned front_seg_size = bio->bi_seg_front_size;
+       bool do_split = true;
+       struct bio *new = NULL;
 
        bio_for_each_segment(bv, bio, iter) {
                if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
@@ -98,7 +101,7 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
 
                        seg_size += bv.bv_len;
                        bvprv = bv;
-                       bvprvp = &bv;
+                       bvprvp = &bvprv;
                        sectors += bv.bv_len >> 9;
                        continue;
                }
@@ -108,16 +111,29 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
 
                nsegs++;
                bvprv = bv;
-               bvprvp = &bv;
+               bvprvp = &bvprv;
                seg_size = bv.bv_len;
                sectors += bv.bv_len >> 9;
+
+               if (nsegs == 1 && seg_size > front_seg_size)
+                       front_seg_size = seg_size;
        }
 
-       *segs = nsegs;
-       return NULL;
+       do_split = false;
 split:
        *segs = nsegs;
-       return bio_split(bio, sectors, GFP_NOIO, bs);
+
+       if (do_split) {
+               new = bio_split(bio, sectors, GFP_NOIO, bs);
+               if (new)
+                       bio = new;
+       }
+
+       bio->bi_seg_front_size = front_seg_size;
+       if (seg_size > bio->bi_seg_back_size)
+               bio->bi_seg_back_size = seg_size;
+
+       return do_split ? new : NULL;
 }
 
 void blk_queue_split(struct request_queue *q, struct bio **bio,
@@ -412,6 +428,12 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        if (sg)
                sg_mark_end(sg);
 
+       /*
+        * Something must have been wrong if the figured number of
+        * segment is bigger than number of req's physical segments
+        */
+       WARN_ON(nsegs > rq->nr_phys_segments);
+
        return nsegs;
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
index 86bd5b25288e29c0415700db4993cd239183366e..6d6f8feb48c08ab875e67c496193a743709b0621 100644 (file)
@@ -358,7 +358,7 @@ static void blk_mq_ipi_complete_request(struct request *rq)
        put_cpu();
 }
 
-void __blk_mq_complete_request(struct request *rq)
+static void __blk_mq_complete_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
@@ -1291,15 +1291,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
                blk_mq_bio_to_request(rq, bio);
 
                /*
-                * we do limited pluging. If bio can be merged, do merge.
+                * We do limited pluging. If the bio can be merged, do that.
                 * Otherwise the existing request in the plug list will be
                 * issued. So the plug list will have one request at most
                 */
                if (plug) {
                        /*
                         * The plug list might get flushed before this. If that
-                        * happens, same_queue_rq is invalid and plug list is empty
-                        **/
+                        * happens, same_queue_rq is invalid and plug list is
+                        * empty
+                        */
                        if (same_queue_rq && !list_empty(&plug->mq_list)) {
                                old_rq = same_queue_rq;
                                list_del_init(&old_rq->queuelist);
@@ -1380,12 +1381,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
                blk_mq_bio_to_request(rq, bio);
                if (!request_count)
                        trace_block_plug(q);
-               else if (request_count >= BLK_MAX_REQUEST_COUNT) {
+
+               blk_mq_put_ctx(data.ctx);
+
+               if (request_count >= BLK_MAX_REQUEST_COUNT) {
                        blk_flush_plug_list(plug, false);
                        trace_block_plug(q);
                }
+
                list_add_tail(&rq->queuelist, &plug->mq_list);
-               blk_mq_put_ctx(data.ctx);
                return cookie;
        }
 
index b44dce165761268c1f0a6bd64db78451f68d912f..713820b47b3182c85331f2638d44449cfdab3bbe 100644 (file)
@@ -25,7 +25,6 @@ struct blk_mq_ctx {
        struct kobject          kobj;
 } ____cacheline_aligned_in_smp;
 
-void __blk_mq_complete_request(struct request *rq);
 void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async);
 void blk_mq_freeze_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
index 246dfb16c3d988c4f84749065a66977b825c98b5..aa40aa93381b661b73d5aa0f531e247e148c56a0 100644 (file)
@@ -158,11 +158,13 @@ void blk_abort_request(struct request *req)
 {
        if (blk_mark_rq_complete(req))
                return;
-       blk_delete_timer(req);
-       if (req->q->mq_ops)
+
+       if (req->q->mq_ops) {
                blk_mq_rq_timed_out(req, false);
-       else
+       } else {
+               blk_delete_timer(req);
                blk_rq_timed_out(req);
+       }
 }
 EXPORT_SYMBOL_GPL(blk_abort_request);
 
index da722eb786df6afd6ff0e567024fe2f7b02488e7..c43926d3d74d0578216d1a699b1dfefff2a899df 100644 (file)
@@ -72,8 +72,6 @@ void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 bool __blk_end_bidi_request(struct request *rq, int error,
                            unsigned int nr_bytes, unsigned int bidi_bytes);
-int blk_queue_enter(struct request_queue *q, gfp_t gfp);
-void blk_queue_exit(struct request_queue *q);
 void blk_freeze_queue(struct request_queue *q);
 
 static inline void blk_queue_enter_live(struct request_queue *q)
index 3de89d4690f3bf3e0d9abec1976a379b5dc171e5..a163c487cf38c8250ccbf0ec7beac913672796f0 100644 (file)
@@ -21,10 +21,10 @@ static void noop_merged_requests(struct request_queue *q, struct request *rq,
 static int noop_dispatch(struct request_queue *q, int force)
 {
        struct noop_data *nd = q->elevator->elevator_data;
+       struct request *rq;
 
-       if (!list_empty(&nd->queue)) {
-               struct request *rq;
-               rq = list_entry(nd->queue.next, struct request, queuelist);
+       rq = list_first_entry_or_null(&nd->queue, struct request, queuelist);
+       if (rq) {
                list_del_init(&rq->queuelist);
                elv_dispatch_sort(q, rq);
                return 1;
@@ -46,7 +46,7 @@ noop_former_request(struct request_queue *q, struct request *rq)
 
        if (rq->queuelist.prev == &nd->queue)
                return NULL;
-       return list_entry(rq->queuelist.prev, struct request, queuelist);
+       return list_prev_entry(rq, queuelist);
 }
 
 static struct request *
@@ -56,7 +56,7 @@ noop_latter_request(struct request_queue *q, struct request *rq)
 
        if (rq->queuelist.next == &nd->queue)
                return NULL;
-       return list_entry(rq->queuelist.next, struct request, queuelist);
+       return list_next_entry(rq, queuelist);
 }
 
 static int noop_init_queue(struct request_queue *q, struct elevator_type *e)
index c2c48ec64b2709c5f252e164bc3397df0c439210..621317ac4d59f5fd75e433718a194bad7b1c2a56 100644 (file)
@@ -32,7 +32,7 @@ int mac_partition(struct parsed_partitions *state)
        Sector sect;
        unsigned char *data;
        int slot, blocks_in_map;
-       unsigned secsize;
+       unsigned secsize, datasize, partoffset;
 #ifdef CONFIG_PPC_PMAC
        int found_root = 0;
        int found_root_goodness = 0;
@@ -50,10 +50,14 @@ int mac_partition(struct parsed_partitions *state)
        }
        secsize = be16_to_cpu(md->block_size);
        put_dev_sector(sect);
-       data = read_part_sector(state, secsize/512, &sect);
+       datasize = round_down(secsize, 512);
+       data = read_part_sector(state, datasize / 512, &sect);
        if (!data)
                return -1;
-       part = (struct mac_partition *) (data + secsize%512);
+       partoffset = secsize % 512;
+       if (partoffset + sizeof(*part) > datasize)
+               return -1;
+       part = (struct mac_partition *) (data + partoffset);
        if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
                put_dev_sector(sect);
                return 0;               /* not a MacOS disk */
index 3000ea3b6687451df7b5459e01cbf4215f9e9c85..021d39c0ba75a8ce3c8c6cb4ea2c41cddd954ad7 100644 (file)
@@ -531,7 +531,11 @@ int x509_decode_time(time64_t *_t,  size_t hdrlen,
        if (*p != 'Z')
                goto unsupported_time;
 
-       mon_len = month_lengths[mon];
+       if (year < 1970 ||
+           mon < 1 || mon > 12)
+               goto invalid_time;
+
+       mon_len = month_lengths[mon - 1];
        if (mon == 2) {
                if (year % 4 == 0) {
                        mon_len = 29;
@@ -543,14 +547,12 @@ int x509_decode_time(time64_t *_t,  size_t hdrlen,
                }
        }
 
-       if (year < 1970 ||
-           mon < 1 || mon > 12 ||
-           day < 1 || day > mon_len ||
+       if (day < 1 || day > mon_len ||
            hour > 23 ||
            min > 59 ||
            sec > 59)
                goto invalid_time;
-       
+
        *_t = mktime64(year, mon, day, hour, min, sec);
        return 0;
 
index 73d039156ea7694f14a444dea3ccbeda6c45a564..795d0ca714bfe45f25b97d3e6f566088925f5875 100644 (file)
@@ -63,6 +63,7 @@ obj-$(CONFIG_FB_I810)           += video/fbdev/i810/
 obj-$(CONFIG_FB_INTEL)          += video/fbdev/intelfb/
 
 obj-$(CONFIG_PARPORT)          += parport/
+obj-$(CONFIG_NVM)              += lightnvm/
 obj-y                          += base/ block/ misc/ mfd/ nfc/
 obj-$(CONFIG_LIBNVDIMM)                += nvdimm/
 obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
@@ -70,7 +71,6 @@ obj-$(CONFIG_NUBUS)           += nubus/
 obj-y                          += macintosh/
 obj-$(CONFIG_IDE)              += ide/
 obj-$(CONFIG_SCSI)             += scsi/
-obj-$(CONFIG_NVM)              += lightnvm/
 obj-y                          += nvme/
 obj-$(CONFIG_ATA)              += ata/
 obj-$(CONFIG_TARGET_CORE)      += target/
index 06a67d5f28461a0ea5a29f7791f7865e45979082..296b7a14893aabba895c578e8671e36b34875a37 100644 (file)
@@ -103,7 +103,12 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        pdevinfo.res = resources;
        pdevinfo.num_res = count;
        pdevinfo.fwnode = acpi_fwnode_handle(adev);
-       pdevinfo.dma_mask = acpi_check_dma(adev, NULL) ? DMA_BIT_MASK(32) : 0;
+
+       if (acpi_dma_supported(adev))
+               pdevinfo.dma_mask = DMA_BIT_MASK(32);
+       else
+               pdevinfo.dma_mask = 0;
+
        pdev = platform_device_register_full(&pdevinfo);
        if (IS_ERR(pdev))
                dev_err(&adev->dev, "platform device creation failed: %ld\n",
index 5778e8e4313a191629dbe00a459e0c2fb5e1ec58..3405f7a41e2576415d344eb0782323ba469ea0a4 100644 (file)
@@ -77,6 +77,12 @@ module_param(allow_duplicates, bool, 0644);
 static int disable_backlight_sysfs_if = -1;
 module_param(disable_backlight_sysfs_if, int, 0444);
 
+static bool device_id_scheme = false;
+module_param(device_id_scheme, bool, 0444);
+
+static bool only_lcd = false;
+module_param(only_lcd, bool, 0444);
+
 static int register_count;
 static DEFINE_MUTEX(register_count_mutex);
 static struct mutex video_list_lock;
@@ -394,6 +400,18 @@ static int video_disable_backlight_sysfs_if(
        return 0;
 }
 
+static int video_set_device_id_scheme(const struct dmi_system_id *d)
+{
+       device_id_scheme = true;
+       return 0;
+}
+
+static int video_enable_only_lcd(const struct dmi_system_id *d)
+{
+       only_lcd = true;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -455,6 +473,33 @@ static struct dmi_system_id video_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE R830"),
                },
        },
+       /*
+        * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
+        * but the IDs actually follow the Device ID Scheme.
+        */
+       {
+        /* https://bugzilla.kernel.org/show_bug.cgi?id=104121 */
+        .callback = video_set_device_id_scheme,
+        .ident = "ESPRIMO Mobile M9410",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
+               },
+       },
+       /*
+        * Some machines have multiple video output devices, but only the one
+        * that is the type of LCD can do the backlight control so we should not
+        * register backlight interface for other video output devices.
+        */
+       {
+        /* https://bugzilla.kernel.org/show_bug.cgi?id=104121 */
+        .callback = video_enable_only_lcd,
+        .ident = "ESPRIMO Mobile M9410",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
+               },
+       },
        {}
 };
 
@@ -1003,7 +1048,7 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
 
        attribute = acpi_video_get_device_attr(video, device_id);
 
-       if (attribute && attribute->device_id_scheme) {
+       if (attribute && (attribute->device_id_scheme || device_id_scheme)) {
                switch (attribute->display_type) {
                case ACPI_VIDEO_DISPLAY_CRT:
                        data->flags.crt = 1;
@@ -1568,15 +1613,6 @@ static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
        static int count;
        char *name;
 
-       /*
-        * Do not create backlight device for video output
-        * device that is not in the enumerated list.
-        */
-       if (!acpi_video_device_in_dod(device)) {
-               dev_dbg(&device->dev->dev, "not in _DOD list, ignore\n");
-               return;
-       }
-
        result = acpi_video_init_brightness(device);
        if (result)
                return;
@@ -1657,6 +1693,22 @@ static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
        mutex_unlock(&video->device_list_lock);
 }
 
+static bool acpi_video_should_register_backlight(struct acpi_video_device *dev)
+{
+       /*
+        * Do not create backlight device for video output
+        * device that is not in the enumerated list.
+        */
+       if (!acpi_video_device_in_dod(dev)) {
+               dev_dbg(&dev->dev->dev, "not in _DOD list, ignore\n");
+               return false;
+       }
+
+       if (only_lcd)
+               return dev->flags.lcd;
+       return true;
+}
+
 static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
 {
        struct acpi_video_device *dev;
@@ -1670,8 +1722,10 @@ static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
                return 0;
 
        mutex_lock(&video->device_list_lock);
-       list_for_each_entry(dev, &video->video_device_list, entry)
-               acpi_video_dev_register_backlight(dev);
+       list_for_each_entry(dev, &video->video_device_list, entry) {
+               if (acpi_video_should_register_backlight(dev))
+                       acpi_video_dev_register_backlight(dev);
+       }
        mutex_unlock(&video->device_list_lock);
 
        video->backlight_registered = true;
index 3c083d2cc4342049a97fae02407fb64b7e553036..6730f965b3793f25ba73125a00b18f346decf75f 100644 (file)
@@ -304,7 +304,7 @@ EXPORT_SYMBOL_GPL(acpi_get_psd_map);
 
 static int register_pcc_channel(int pcc_subspace_idx)
 {
-       struct acpi_pcct_subspace *cppc_ss;
+       struct acpi_pcct_hw_reduced *cppc_ss;
        unsigned int len;
 
        if (pcc_subspace_idx >= 0) {
index f61a7c83454063a5e77ebf35e13cb4bb1431891b..b420fb46669dd698c4d346559c325c0f4afeaf4d 100644 (file)
@@ -1103,7 +1103,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
        }
 
 err_exit:
-       if (result && q)
+       if (result)
                acpi_ec_delete_query(q);
        if (data)
                *data = value;
index 1470ae4f98c07ce6e358bd53bf17b0c0b209b1cb..5ea5dc219f563702e5bad7141832af2861e9144a 100644 (file)
@@ -168,7 +168,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
        struct list_head *physnode_list;
        unsigned int node_id;
        int retval = -EINVAL;
-       bool coherent;
+       enum dev_dma_attr attr;
 
        if (has_acpi_companion(dev)) {
                if (acpi_dev) {
@@ -225,8 +225,10 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
        if (!has_acpi_companion(dev))
                ACPI_COMPANION_SET(dev, acpi_dev);
 
-       if (acpi_check_dma(acpi_dev, &coherent))
-               arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+       attr = acpi_get_dma_attr(acpi_dev);
+       if (attr != DEV_DMA_NOT_SUPPORTED)
+               arch_setup_dma_ops(dev, 0, 0, NULL,
+                                  attr == DEV_DMA_COHERENT);
 
        acpi_physnode_link_name(physical_node_name, node_id);
        retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
index bf034f8b7c1acde77f90ded7f39f70dbd636b7db..2fa8304171e09b70e501dcab7892a9b443c84695 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/dmi.h>
 #include "sbshc.h"
 
 #define PREFIX "ACPI: "
@@ -30,6 +29,7 @@ struct acpi_smb_hc {
        u8 query_bit;
        smbus_alarm_callback callback;
        void *context;
+       bool done;
 };
 
 static int acpi_smbus_hc_add(struct acpi_device *device);
@@ -88,8 +88,6 @@ enum acpi_smb_offset {
        ACPI_SMB_ALARM_DATA = 0x26,     /* 2 bytes alarm data */
 };
 
-static bool macbook;
-
 static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
 {
        return ec_read(hc->offset + address, data);
@@ -100,27 +98,11 @@ static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data)
        return ec_write(hc->offset + address, data);
 }
 
-static inline int smb_check_done(struct acpi_smb_hc *hc)
-{
-       union acpi_smb_status status = {.raw = 0};
-       smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw);
-       return status.fields.done && (status.fields.status == SMBUS_OK);
-}
-
 static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout)
 {
-       if (wait_event_timeout(hc->wait, smb_check_done(hc),
-                              msecs_to_jiffies(timeout)))
+       if (wait_event_timeout(hc->wait, hc->done, msecs_to_jiffies(timeout)))
                return 0;
-       /*
-        * After the timeout happens, OS will try to check the status of SMbus.
-        * If the status is what OS expected, it will be regarded as the bogus
-        * timeout.
-        */
-       if (smb_check_done(hc))
-               return 0;
-       else
-               return -ETIME;
+       return -ETIME;
 }
 
 static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
@@ -135,8 +117,7 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
        }
 
        mutex_lock(&hc->lock);
-       if (macbook)
-               udelay(5);
+       hc->done = false;
        if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
                goto end;
        if (temp) {
@@ -235,8 +216,10 @@ static int smbus_alarm(void *context)
        if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw))
                return 0;
        /* Check if it is only a completion notify */
-       if (status.fields.done)
+       if (status.fields.done && status.fields.status == SMBUS_OK) {
+               hc->done = true;
                wake_up(&hc->wait);
+       }
        if (!status.fields.alarm)
                return 0;
        mutex_lock(&hc->lock);
@@ -262,29 +245,12 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
                              acpi_handle handle, acpi_ec_query_func func,
                              void *data);
 
-static int macbook_dmi_match(const struct dmi_system_id *d)
-{
-       pr_debug("Detected MacBook, enabling workaround\n");
-       macbook = true;
-       return 0;
-}
-
-static struct dmi_system_id acpi_smbus_dmi_table[] = {
-       { macbook_dmi_match, "Apple MacBook", {
-         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
-         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
-       },
-       { },
-};
-
 static int acpi_smbus_hc_add(struct acpi_device *device)
 {
        int status;
        unsigned long long val;
        struct acpi_smb_hc *hc;
 
-       dmi_check_system(acpi_smbus_dmi_table);
-
        if (!device)
                return -EINVAL;
 
index daf9fc8329e64c41817269d0b6c437e3ccb2d1e3..78d5f02a073bb1c9e84beaeaf2f38b6f54125333 100644 (file)
@@ -1308,6 +1308,48 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
        kfree(pnp->unique_id);
 }
 
+/**
+ * acpi_dma_supported - Check DMA support for the specified device.
+ * @adev: The pointer to acpi device
+ *
+ * Return false if DMA is not supported. Otherwise, return true
+ */
+bool acpi_dma_supported(struct acpi_device *adev)
+{
+       if (!adev)
+               return false;
+
+       if (adev->flags.cca_seen)
+               return true;
+
+       /*
+       * Per ACPI 6.0 sec 6.2.17, assume devices can do cache-coherent
+       * DMA on "Intel platforms".  Presumably that includes all x86 and
+       * ia64, and other arches will set CONFIG_ACPI_CCA_REQUIRED=y.
+       */
+       if (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED))
+               return true;
+
+       return false;
+}
+
+/**
+ * acpi_get_dma_attr - Check the supported DMA attr for the specified device.
+ * @adev: The pointer to acpi device
+ *
+ * Return enum dev_dma_attr.
+ */
+enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
+{
+       if (!acpi_dma_supported(adev))
+               return DEV_DMA_NOT_SUPPORTED;
+
+       if (adev->flags.coherent_dma)
+               return DEV_DMA_COHERENT;
+       else
+               return DEV_DMA_NON_COHERENT;
+}
+
 static void acpi_init_coherency(struct acpi_device *adev)
 {
        unsigned long long cca = 0;
index 0d3a384b508a9c4782b7fe20ca1264dc3b11b0bf..daaf1c4e1e0f78657afb1f140b49e0cf3162d6df 100644 (file)
@@ -232,6 +232,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                          "900X3C/900X3D/900X3E/900X4C/900X4D"),
                },
        },
+       {
+        /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
+        .callback = video_detect_force_video,
+        .ident = "Dell XPS14 L421X",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+               },
+       },
        {
         /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
         .callback = video_detect_force_video,
index 8b3a7861fa44c205490788d4538e5da300270ffb..7e959f90c0203f9b94124ab73867e4a72bd11188 100644 (file)
@@ -3696,9 +3696,6 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                 */
                shost->max_host_blocked = 1;
 
-               if (scsi_init_shared_tag_map(shost, host->n_tags))
-                       goto err_add;
-
                rc = scsi_add_host_with_dma(ap->scsi_host,
                                                &ap->tdev, ap->host->dev);
                if (rc)
index 80e29887038830a7bac36fe79d8c53912b828d81..e03b1ad25a906334078490786dbd1406ac9ca76b 100644 (file)
@@ -321,8 +321,7 @@ static int genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
                if (stat > PM_QOS_FLAGS_NONE)
                        return -EBUSY;
 
-               if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-                   || pdd->dev->power.irq_safe))
+               if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
                        not_suspended++;
        }
 
@@ -1312,13 +1311,17 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                           struct generic_pm_domain *subdomain)
 {
-       struct gpd_link *link;
+       struct gpd_link *link, *itr;
        int ret = 0;
 
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
            || genpd == subdomain)
                return -EINVAL;
 
+       link = kzalloc(sizeof(*link), GFP_KERNEL);
+       if (!link)
+               return -ENOMEM;
+
        mutex_lock(&genpd->lock);
        mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
 
@@ -1328,18 +1331,13 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                goto out;
        }
 
-       list_for_each_entry(link, &genpd->master_links, master_node) {
-               if (link->slave == subdomain && link->master == genpd) {
+       list_for_each_entry(itr, &genpd->master_links, master_node) {
+               if (itr->slave == subdomain && itr->master == genpd) {
                        ret = -EINVAL;
                        goto out;
                }
        }
 
-       link = kzalloc(sizeof(*link), GFP_KERNEL);
-       if (!link) {
-               ret = -ENOMEM;
-               goto out;
-       }
        link->master = genpd;
        list_add_tail(&link->master_node, &genpd->master_links);
        link->slave = subdomain;
@@ -1350,7 +1348,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
  out:
        mutex_unlock(&subdomain->lock);
        mutex_unlock(&genpd->lock);
-
+       if (ret)
+               kfree(link);
        return ret;
 }
 EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
index 2709020070551109798c36e517592948ca435cc2..b8e76f75073b47a945b695506bb68176c586a161 100644 (file)
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -27,7 +29,7 @@
  */
 static LIST_HEAD(dev_opp_list);
 /* Lock to allow exclusive modification to the device and opp lists */
-static DEFINE_MUTEX(dev_opp_list_lock);
+DEFINE_MUTEX(dev_opp_list_lock);
 
 #define opp_rcu_lockdep_assert()                                       \
 do {                                                                   \
@@ -79,14 +81,18 @@ static struct device_opp *_managed_opp(const struct device_node *np)
  * Return: pointer to 'struct device_opp' if found, otherwise -ENODEV or
  * -EINVAL based on type of error.
  *
- * Locking: This function must be called under rcu_read_lock(). device_opp
- * is a RCU protected pointer. This means that device_opp is valid as long
- * as we are under RCU lock.
+ * Locking: For readers, this function must be called under rcu_read_lock().
+ * device_opp is a RCU protected pointer, which means that device_opp is valid
+ * as long as we are under RCU lock.
+ *
+ * For Writers, this function must be called with dev_opp_list_lock held.
  */
 struct device_opp *_find_device_opp(struct device *dev)
 {
        struct device_opp *dev_opp;
 
+       opp_rcu_lockdep_assert();
+
        if (IS_ERR_OR_NULL(dev)) {
                pr_err("%s: Invalid parameters\n", __func__);
                return ERR_PTR(-EINVAL);
@@ -701,7 +707,7 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
 }
 
 /**
- * _opp_add_dynamic() - Allocate a dynamic OPP.
+ * _opp_add_v1() - Allocate a OPP based on v1 bindings.
  * @dev:       device for which we do this operation
  * @freq:      Frequency in Hz for this OPP
  * @u_volt:    Voltage in uVolts for this OPP
@@ -727,8 +733,8 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
  *             Duplicate OPPs (both freq and volt are same) and !opp->available
  * -ENOMEM     Memory allocation failure
  */
-static int _opp_add_dynamic(struct device *dev, unsigned long freq,
-                           long u_volt, bool dynamic)
+static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
+                      bool dynamic)
 {
        struct device_opp *dev_opp;
        struct dev_pm_opp *new_opp;
@@ -770,9 +776,10 @@ static int _opp_add_dynamic(struct device *dev, unsigned long freq,
 }
 
 /* TODO: Support multiple regulators */
-static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
+static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev)
 {
        u32 microvolt[3] = {0};
+       u32 val;
        int count, ret;
 
        /* Missing property isn't a problem, but an invalid entry is */
@@ -805,6 +812,9 @@ static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
        opp->u_volt_min = microvolt[1];
        opp->u_volt_max = microvolt[2];
 
+       if (!of_property_read_u32(opp->np, "opp-microamp", &val))
+               opp->u_amp = val;
+
        return 0;
 }
 
@@ -869,13 +879,10 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
        if (!of_property_read_u32(np, "clock-latency-ns", &val))
                new_opp->clock_latency_ns = val;
 
-       ret = opp_get_microvolt(new_opp, dev);
+       ret = opp_parse_supplies(new_opp, dev);
        if (ret)
                goto free_opp;
 
-       if (!of_property_read_u32(new_opp->np, "opp-microamp", &val))
-               new_opp->u_amp = val;
-
        ret = _opp_add(dev, new_opp, dev_opp);
        if (ret)
                goto free_opp;
@@ -939,7 +946,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
  */
 int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 {
-       return _opp_add_dynamic(dev, freq, u_volt, true);
+       return _opp_add_v1(dev, freq, u_volt, true);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
@@ -1172,13 +1179,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
        struct device_opp *dev_opp;
        int ret = 0, count = 0;
 
+       mutex_lock(&dev_opp_list_lock);
+
        dev_opp = _managed_opp(opp_np);
        if (dev_opp) {
                /* OPPs are already managed */
                if (!_add_list_dev(dev, dev_opp))
                        ret = -ENOMEM;
+               mutex_unlock(&dev_opp_list_lock);
                return ret;
        }
+       mutex_unlock(&dev_opp_list_lock);
 
        /* We have opp-list node now, iterate over it and add OPPs */
        for_each_available_child_of_node(opp_np, np) {
@@ -1196,15 +1207,20 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
        if (WARN_ON(!count))
                return -ENOENT;
 
+       mutex_lock(&dev_opp_list_lock);
+
        dev_opp = _find_device_opp(dev);
        if (WARN_ON(IS_ERR(dev_opp))) {
                ret = PTR_ERR(dev_opp);
+               mutex_unlock(&dev_opp_list_lock);
                goto free_table;
        }
 
        dev_opp->np = opp_np;
        dev_opp->shared_opp = of_property_read_bool(opp_np, "opp-shared");
 
+       mutex_unlock(&dev_opp_list_lock);
+
        return 0;
 
 free_table:
@@ -1241,7 +1257,7 @@ static int _of_add_opp_table_v1(struct device *dev)
                unsigned long freq = be32_to_cpup(val++) * 1000;
                unsigned long volt = be32_to_cpup(val++);
 
-               if (_opp_add_dynamic(dev, freq, volt, false))
+               if (_opp_add_v1(dev, freq, volt, false))
                        dev_warn(dev, "%s: Failed to add OPP %ld\n",
                                 __func__, freq);
                nr -= 2;
index 7654c5606307f7e3d71903385964e3af9a71caea..7b445e88a0d559f091918be5e841f6a1380a33da 100644 (file)
@@ -10,6 +10,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/err.h>
@@ -124,12 +127,12 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
        struct device *dev;
        int cpu, ret = 0;
 
-       rcu_read_lock();
+       mutex_lock(&dev_opp_list_lock);
 
        dev_opp = _find_device_opp(cpu_dev);
        if (IS_ERR(dev_opp)) {
                ret = -EINVAL;
-               goto out_rcu_read_unlock;
+               goto unlock;
        }
 
        for_each_cpu(cpu, cpumask) {
@@ -150,10 +153,10 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
                        continue;
                }
        }
-out_rcu_read_unlock:
-       rcu_read_unlock();
+unlock:
+       mutex_unlock(&dev_opp_list_lock);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
 
index dcb38f78dae429dad1e6387c53fd984b967f64a4..7366b2aa8997897f89890cf99a4990d83e61a5a6 100644 (file)
@@ -21,6 +21,9 @@
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
 
+/* Lock to allow exclusive modification to the device and opp lists */
+extern struct mutex dev_opp_list_lock;
+
 /*
  * Internal data structure organization with the OPP layer library is as
  * follows:
index eb6e67451decee999901493d9182ed6c9cf21bf9..0d77cd6fd8d11653c789fa8834e8eb53b801a6d9 100644 (file)
@@ -68,6 +68,9 @@ int dev_pm_set_wake_irq(struct device *dev, int irq)
        struct wake_irq *wirq;
        int err;
 
+       if (irq < 0)
+               return -EINVAL;
+
        wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);
        if (!wirq)
                return -ENOMEM;
@@ -167,6 +170,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
        struct wake_irq *wirq;
        int err;
 
+       if (irq < 0)
+               return -EINVAL;
+
        wirq = kzalloc(sizeof(*wirq), GFP_KERNEL);
        if (!wirq)
                return -ENOMEM;
index de40623bbd8a748fd81f3208810046d05861a75c..1325ff225cc4a5b37a7c0b3fe0b3d7946c37811e 100644 (file)
@@ -598,18 +598,34 @@ unsigned int device_get_child_node_count(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_get_child_node_count);
 
-bool device_dma_is_coherent(struct device *dev)
+bool device_dma_supported(struct device *dev)
 {
-       bool coherent = false;
-
+       /* For DT, this is always supported.
+        * For ACPI, this depends on CCA, which
+        * is determined by the acpi_dma_supported().
+        */
        if (IS_ENABLED(CONFIG_OF) && dev->of_node)
-               coherent = of_dma_is_coherent(dev->of_node);
-       else
-               acpi_check_dma(ACPI_COMPANION(dev), &coherent);
+               return true;
+
+       return acpi_dma_supported(ACPI_COMPANION(dev));
+}
+EXPORT_SYMBOL_GPL(device_dma_supported);
 
-       return coherent;
+enum dev_dma_attr device_get_dma_attr(struct device *dev)
+{
+       enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
+
+       if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+               if (of_dma_is_coherent(dev->of_node))
+                       attr = DEV_DMA_COHERENT;
+               else
+                       attr = DEV_DMA_NON_COHERENT;
+       } else
+               attr = acpi_get_dma_attr(ACPI_COMPANION(dev));
+
+       return attr;
 }
-EXPORT_SYMBOL_GPL(device_dma_is_coherent);
+EXPORT_SYMBOL_GPL(device_get_dma_attr);
 
 /**
  * device_get_phy_mode - Get phy mode for given device
index c9f9c30d646756296e0e4bdd212a33ba28a479b6..a5880f4ab40eb069bda60d6403b223d61ff1db80 100644 (file)
@@ -337,6 +337,9 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
                goto io_error;
 
        if (unlikely(bio->bi_rw & REQ_DISCARD)) {
+               if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
+                   bio->bi_iter.bi_size & PAGE_MASK)
+                       goto io_error;
                discard_from_brd(brd, sector, bio->bi_iter.bi_size);
                goto out;
        }
index a28a562f7b7f245355db7d536e0558c78cc7e374..3457ac8c03e2f3cfe10c8a2ccc26f9a706039831 100644 (file)
@@ -3810,7 +3810,6 @@ static int mtip_block_initialize(struct driver_data *dd)
        sector_t capacity;
        unsigned int index = 0;
        struct kobject *kobj;
-       unsigned char thd_name[16];
 
        if (dd->disk)
                goto skip_create_disk; /* hw init done, before rebuild */
@@ -3958,10 +3957,9 @@ static int mtip_block_initialize(struct driver_data *dd)
        }
 
 start_service_thread:
-       sprintf(thd_name, "mtip_svc_thd_%02d", index);
        dd->mtip_svc_handler = kthread_create_on_node(mtip_service_thread,
-                                               dd, dd->numa_node, "%s",
-                                               thd_name);
+                                               dd, dd->numa_node,
+                                               "mtip_svc_thd_%02d", index);
 
        if (IS_ERR(dd->mtip_svc_handler)) {
                dev_err(&dd->pdev->dev, "service thread failed to start\n");
index 6255d1c4bba46c802548806ff95ee213ffd3f0e6..5c8ba5484d86b14edaaf20cfd215591950826a76 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/blk-mq.h>
 #include <linux/hrtimer.h>
+#include <linux/lightnvm.h>
 
 struct nullb_cmd {
        struct list_head list;
@@ -39,12 +40,14 @@ struct nullb {
 
        struct nullb_queue *queues;
        unsigned int nr_queues;
+       char disk_name[DISK_NAME_LEN];
 };
 
 static LIST_HEAD(nullb_list);
 static struct mutex lock;
 static int null_major;
 static int nullb_indexes;
+static struct kmem_cache *ppa_cache;
 
 struct completion_queue {
        struct llist_head list;
@@ -119,6 +122,10 @@ static int nr_devices = 2;
 module_param(nr_devices, int, S_IRUGO);
 MODULE_PARM_DESC(nr_devices, "Number of devices to register");
 
+static bool use_lightnvm;
+module_param(use_lightnvm, bool, S_IRUGO);
+MODULE_PARM_DESC(use_lightnvm, "Register as a LightNVM device");
+
 static int irqmode = NULL_IRQ_SOFTIRQ;
 
 static int null_set_irqmode(const char *str, const struct kernel_param *kp)
@@ -427,15 +434,156 @@ static void null_del_dev(struct nullb *nullb)
 {
        list_del_init(&nullb->list);
 
-       del_gendisk(nullb->disk);
+       if (use_lightnvm)
+               nvm_unregister(nullb->disk_name);
+       else
+               del_gendisk(nullb->disk);
        blk_cleanup_queue(nullb->q);
        if (queue_mode == NULL_Q_MQ)
                blk_mq_free_tag_set(&nullb->tag_set);
-       put_disk(nullb->disk);
+       if (!use_lightnvm)
+               put_disk(nullb->disk);
        cleanup_queues(nullb);
        kfree(nullb);
 }
 
+#ifdef CONFIG_NVM
+
+static void null_lnvm_end_io(struct request *rq, int error)
+{
+       struct nvm_rq *rqd = rq->end_io_data;
+       struct nvm_dev *dev = rqd->dev;
+
+       dev->mt->end_io(rqd, error);
+
+       blk_put_request(rq);
+}
+
+static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+{
+       struct request *rq;
+       struct bio *bio = rqd->bio;
+
+       rq = blk_mq_alloc_request(q, bio_rw(bio), GFP_KERNEL, 0);
+       if (IS_ERR(rq))
+               return -ENOMEM;
+
+       rq->cmd_type = REQ_TYPE_DRV_PRIV;
+       rq->__sector = bio->bi_iter.bi_sector;
+       rq->ioprio = bio_prio(bio);
+
+       if (bio_has_data(bio))
+               rq->nr_phys_segments = bio_phys_segments(q, bio);
+
+       rq->__data_len = bio->bi_iter.bi_size;
+       rq->bio = rq->biotail = bio;
+
+       rq->end_io_data = rqd;
+
+       blk_execute_rq_nowait(q, NULL, rq, 0, null_lnvm_end_io);
+
+       return 0;
+}
+
+static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
+{
+       sector_t size = gb * 1024 * 1024 * 1024ULL;
+       sector_t blksize;
+       struct nvm_id_group *grp;
+
+       id->ver_id = 0x1;
+       id->vmnt = 0;
+       id->cgrps = 1;
+       id->cap = 0x3;
+       id->dom = 0x1;
+
+       id->ppaf.blk_offset = 0;
+       id->ppaf.blk_len = 16;
+       id->ppaf.pg_offset = 16;
+       id->ppaf.pg_len = 16;
+       id->ppaf.sect_offset = 32;
+       id->ppaf.sect_len = 8;
+       id->ppaf.pln_offset = 40;
+       id->ppaf.pln_len = 8;
+       id->ppaf.lun_offset = 48;
+       id->ppaf.lun_len = 8;
+       id->ppaf.ch_offset = 56;
+       id->ppaf.ch_len = 8;
+
+       do_div(size, bs); /* convert size to pages */
+       do_div(size, 256); /* concert size to pgs pr blk */
+       grp = &id->groups[0];
+       grp->mtype = 0;
+       grp->fmtype = 0;
+       grp->num_ch = 1;
+       grp->num_pg = 256;
+       blksize = size;
+       do_div(size, (1 << 16));
+       grp->num_lun = size + 1;
+       do_div(blksize, grp->num_lun);
+       grp->num_blk = blksize;
+       grp->num_pln = 1;
+
+       grp->fpg_sz = bs;
+       grp->csecs = bs;
+       grp->trdt = 25000;
+       grp->trdm = 25000;
+       grp->tprt = 500000;
+       grp->tprm = 500000;
+       grp->tbet = 1500000;
+       grp->tbem = 1500000;
+       grp->mpos = 0x010101; /* single plane rwe */
+       grp->cpar = hw_queue_depth;
+
+       return 0;
+}
+
+static void *null_lnvm_create_dma_pool(struct request_queue *q, char *name)
+{
+       mempool_t *virtmem_pool;
+
+       virtmem_pool = mempool_create_slab_pool(64, ppa_cache);
+       if (!virtmem_pool) {
+               pr_err("null_blk: Unable to create virtual memory pool\n");
+               return NULL;
+       }
+
+       return virtmem_pool;
+}
+
+static void null_lnvm_destroy_dma_pool(void *pool)
+{
+       mempool_destroy(pool);
+}
+
+static void *null_lnvm_dev_dma_alloc(struct request_queue *q, void *pool,
+                               gfp_t mem_flags, dma_addr_t *dma_handler)
+{
+       return mempool_alloc(pool, mem_flags);
+}
+
+static void null_lnvm_dev_dma_free(void *pool, void *entry,
+                                                       dma_addr_t dma_handler)
+{
+       mempool_free(entry, pool);
+}
+
+static struct nvm_dev_ops null_lnvm_dev_ops = {
+       .identity               = null_lnvm_id,
+       .submit_io              = null_lnvm_submit_io,
+
+       .create_dma_pool        = null_lnvm_create_dma_pool,
+       .destroy_dma_pool       = null_lnvm_destroy_dma_pool,
+       .dev_dma_alloc          = null_lnvm_dev_dma_alloc,
+       .dev_dma_free           = null_lnvm_dev_dma_free,
+
+       /* Simulate nvme protocol restriction */
+       .max_phys_sect          = 64,
+};
+#else
+static struct nvm_dev_ops null_lnvm_dev_ops;
+#endif /* CONFIG_NVM */
+
 static int null_open(struct block_device *bdev, fmode_t mode)
 {
        return 0;
@@ -575,11 +723,6 @@ static int null_add_dev(void)
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
        queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, nullb->q);
 
-       disk = nullb->disk = alloc_disk_node(1, home_node);
-       if (!disk) {
-               rv = -ENOMEM;
-               goto out_cleanup_blk_queue;
-       }
 
        mutex_lock(&lock);
        list_add_tail(&nullb->list, &nullb_list);
@@ -589,6 +732,21 @@ static int null_add_dev(void)
        blk_queue_logical_block_size(nullb->q, bs);
        blk_queue_physical_block_size(nullb->q, bs);
 
+       sprintf(nullb->disk_name, "nullb%d", nullb->index);
+
+       if (use_lightnvm) {
+               rv = nvm_register(nullb->q, nullb->disk_name,
+                                                       &null_lnvm_dev_ops);
+               if (rv)
+                       goto out_cleanup_blk_queue;
+               goto done;
+       }
+
+       disk = nullb->disk = alloc_disk_node(1, home_node);
+       if (!disk) {
+               rv = -ENOMEM;
+               goto out_cleanup_lightnvm;
+       }
        size = gb * 1024 * 1024 * 1024ULL;
        set_capacity(disk, size >> 9);
 
@@ -598,10 +756,15 @@ static int null_add_dev(void)
        disk->fops              = &null_fops;
        disk->private_data      = nullb;
        disk->queue             = nullb->q;
-       sprintf(disk->disk_name, "nullb%d", nullb->index);
+       strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
+
        add_disk(disk);
+done:
        return 0;
 
+out_cleanup_lightnvm:
+       if (use_lightnvm)
+               nvm_unregister(nullb->disk_name);
 out_cleanup_blk_queue:
        blk_cleanup_queue(nullb->q);
 out_cleanup_tags:
@@ -625,6 +788,18 @@ static int __init null_init(void)
                bs = PAGE_SIZE;
        }
 
+       if (use_lightnvm && bs != 4096) {
+               pr_warn("null_blk: LightNVM only supports 4k block size\n");
+               pr_warn("null_blk: defaults block size to 4k\n");
+               bs = 4096;
+       }
+
+       if (use_lightnvm && queue_mode != NULL_Q_MQ) {
+               pr_warn("null_blk: LightNVM only supported for blk-mq\n");
+               pr_warn("null_blk: defaults queue mode to blk-mq\n");
+               queue_mode = NULL_Q_MQ;
+       }
+
        if (queue_mode == NULL_Q_MQ && use_per_node_hctx) {
                if (submit_queues < nr_online_nodes) {
                        pr_warn("null_blk: submit_queues param is set to %u.",
@@ -655,15 +830,27 @@ static int __init null_init(void)
        if (null_major < 0)
                return null_major;
 
+       if (use_lightnvm) {
+               ppa_cache = kmem_cache_create("ppa_cache", 64 * sizeof(u64),
+                                                               0, 0, NULL);
+               if (!ppa_cache) {
+                       pr_err("null_blk: unable to create ppa cache\n");
+                       return -ENOMEM;
+               }
+       }
+
        for (i = 0; i < nr_devices; i++) {
                if (null_add_dev()) {
                        unregister_blkdev(null_major, "nullb");
-                       return -EINVAL;
+                       goto err_ppa;
                }
        }
 
        pr_info("null: module loaded\n");
        return 0;
+err_ppa:
+       kmem_cache_destroy(ppa_cache);
+       return -EINVAL;
 }
 
 static void __exit null_exit(void)
@@ -678,6 +865,8 @@ static void __exit null_exit(void)
                null_del_dev(nullb);
        }
        mutex_unlock(&lock);
+
+       kmem_cache_destroy(ppa_cache);
 }
 
 module_init(null_init);
index 128e7df5b807222ba2d6f50148cb164919a308f7..235708c7c46eee709acb110acb95a28d85ebc946 100644 (file)
@@ -418,8 +418,6 @@ MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (d
 
 static int rbd_img_request_submit(struct rbd_img_request *img_request);
 
-static void rbd_dev_device_release(struct device *dev);
-
 static ssize_t rbd_add(struct bus_type *bus, const char *buf,
                       size_t count);
 static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
@@ -3991,14 +3989,12 @@ static const struct attribute_group *rbd_attr_groups[] = {
        NULL
 };
 
-static void rbd_sysfs_dev_release(struct device *dev)
-{
-}
+static void rbd_dev_release(struct device *dev);
 
 static struct device_type rbd_device_type = {
        .name           = "rbd",
        .groups         = rbd_attr_groups,
-       .release        = rbd_sysfs_dev_release,
+       .release        = rbd_dev_release,
 };
 
 static struct rbd_spec *rbd_spec_get(struct rbd_spec *spec)
@@ -4041,6 +4037,25 @@ static void rbd_spec_free(struct kref *kref)
        kfree(spec);
 }
 
+static void rbd_dev_release(struct device *dev)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+       bool need_put = !!rbd_dev->opts;
+
+       rbd_put_client(rbd_dev->rbd_client);
+       rbd_spec_put(rbd_dev->spec);
+       kfree(rbd_dev->opts);
+       kfree(rbd_dev);
+
+       /*
+        * This is racy, but way better than putting module outside of
+        * the release callback.  The race window is pretty small, so
+        * doing something similar to dm (dm-builtin.c) is overkill.
+        */
+       if (need_put)
+               module_put(THIS_MODULE);
+}
+
 static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
                                         struct rbd_spec *spec,
                                         struct rbd_options *opts)
@@ -4057,6 +4072,11 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
        INIT_LIST_HEAD(&rbd_dev->node);
        init_rwsem(&rbd_dev->header_rwsem);
 
+       rbd_dev->dev.bus = &rbd_bus_type;
+       rbd_dev->dev.type = &rbd_device_type;
+       rbd_dev->dev.parent = &rbd_root_dev;
+       device_initialize(&rbd_dev->dev);
+
        rbd_dev->rbd_client = rbdc;
        rbd_dev->spec = spec;
        rbd_dev->opts = opts;
@@ -4068,15 +4088,21 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc,
        rbd_dev->layout.fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
        rbd_dev->layout.fl_pg_pool = cpu_to_le32((u32) spec->pool_id);
 
+       /*
+        * If this is a mapping rbd_dev (as opposed to a parent one),
+        * pin our module.  We have a ref from do_rbd_add(), so use
+        * __module_get().
+        */
+       if (rbd_dev->opts)
+               __module_get(THIS_MODULE);
+
        return rbd_dev;
 }
 
 static void rbd_dev_destroy(struct rbd_device *rbd_dev)
 {
-       rbd_put_client(rbd_dev->rbd_client);
-       rbd_spec_put(rbd_dev->spec);
-       kfree(rbd_dev->opts);
-       kfree(rbd_dev);
+       if (rbd_dev)
+               put_device(&rbd_dev->dev);
 }
 
 /*
@@ -4702,27 +4728,6 @@ static int rbd_dev_header_info(struct rbd_device *rbd_dev)
        return rbd_dev_v2_header_info(rbd_dev);
 }
 
-static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
-{
-       struct device *dev;
-       int ret;
-
-       dev = &rbd_dev->dev;
-       dev->bus = &rbd_bus_type;
-       dev->type = &rbd_device_type;
-       dev->parent = &rbd_root_dev;
-       dev->release = rbd_dev_device_release;
-       dev_set_name(dev, "%d", rbd_dev->dev_id);
-       ret = device_register(dev);
-
-       return ret;
-}
-
-static void rbd_bus_del_dev(struct rbd_device *rbd_dev)
-{
-       device_unregister(&rbd_dev->dev);
-}
-
 /*
  * Get a unique rbd identifier for the given new rbd_dev, and add
  * the rbd_dev to the global list.
@@ -5225,7 +5230,8 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
        set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
        set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
 
-       ret = rbd_bus_add_dev(rbd_dev);
+       dev_set_name(&rbd_dev->dev, "%d", rbd_dev->dev_id);
+       ret = device_add(&rbd_dev->dev);
        if (ret)
                goto err_out_mapping;
 
@@ -5248,8 +5254,6 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
                unregister_blkdev(rbd_dev->major, rbd_dev->name);
 err_out_id:
        rbd_dev_id_put(rbd_dev);
-       rbd_dev_mapping_clear(rbd_dev);
-
        return ret;
 }
 
@@ -5397,7 +5401,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        struct rbd_spec *spec = NULL;
        struct rbd_client *rbdc;
        bool read_only;
-       int rc = -ENOMEM;
+       int rc;
 
        if (!try_module_get(THIS_MODULE))
                return -ENODEV;
@@ -5405,7 +5409,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        /* parse add command */
        rc = rbd_add_parse_args(buf, &ceph_opts, &rbd_opts, &spec);
        if (rc < 0)
-               goto err_out_module;
+               goto out;
 
        rbdc = rbd_get_client(ceph_opts);
        if (IS_ERR(rbdc)) {
@@ -5432,8 +5436,10 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        }
 
        rbd_dev = rbd_dev_create(rbdc, spec, rbd_opts);
-       if (!rbd_dev)
+       if (!rbd_dev) {
+               rc = -ENOMEM;
                goto err_out_client;
+       }
        rbdc = NULL;            /* rbd_dev now owns this */
        spec = NULL;            /* rbd_dev now owns this */
        rbd_opts = NULL;        /* rbd_dev now owns this */
@@ -5458,10 +5464,13 @@ static ssize_t do_rbd_add(struct bus_type *bus,
                 */
                rbd_dev_header_unwatch_sync(rbd_dev);
                rbd_dev_image_release(rbd_dev);
-               goto err_out_module;
+               goto out;
        }
 
-       return count;
+       rc = count;
+out:
+       module_put(THIS_MODULE);
+       return rc;
 
 err_out_rbd_dev:
        rbd_dev_destroy(rbd_dev);
@@ -5470,12 +5479,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
 err_out_args:
        rbd_spec_put(spec);
        kfree(rbd_opts);
-err_out_module:
-       module_put(THIS_MODULE);
-
-       dout("Error adding device %s\n", buf);
-
-       return (ssize_t)rc;
+       goto out;
 }
 
 static ssize_t rbd_add(struct bus_type *bus,
@@ -5495,17 +5499,15 @@ static ssize_t rbd_add_single_major(struct bus_type *bus,
        return do_rbd_add(bus, buf, count);
 }
 
-static void rbd_dev_device_release(struct device *dev)
+static void rbd_dev_device_release(struct rbd_device *rbd_dev)
 {
-       struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
-
        rbd_free_disk(rbd_dev);
        clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
+       device_del(&rbd_dev->dev);
        rbd_dev_mapping_clear(rbd_dev);
        if (!single_major)
                unregister_blkdev(rbd_dev->major, rbd_dev->name);
        rbd_dev_id_put(rbd_dev);
-       rbd_dev_mapping_clear(rbd_dev);
 }
 
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
@@ -5590,9 +5592,8 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
         * rbd_bus_del_dev() will race with rbd_watch_cb(), resulting
         * in a potential use after free of rbd_dev->disk or rbd_dev.
         */
-       rbd_bus_del_dev(rbd_dev);
+       rbd_dev_device_release(rbd_dev);
        rbd_dev_image_release(rbd_dev);
-       module_put(THIS_MODULE);
 
        return count;
 }
@@ -5663,10 +5664,8 @@ static int rbd_slab_init(void)
        if (rbd_segment_name_cache)
                return 0;
 out_err:
-       if (rbd_obj_request_cache) {
-               kmem_cache_destroy(rbd_obj_request_cache);
-               rbd_obj_request_cache = NULL;
-       }
+       kmem_cache_destroy(rbd_obj_request_cache);
+       rbd_obj_request_cache = NULL;
 
        kmem_cache_destroy(rbd_img_request_cache);
        rbd_img_request_cache = NULL;
index 9f185694875850427e9613aaf725859c7efbfc63..bf500e0e7362baf72f7a4321e5fda55dc4355f9b 100644 (file)
@@ -117,7 +117,7 @@ static struct platform_driver omap_ocp2scp_driver = {
 
 module_platform_driver(omap_ocp2scp_driver);
 
-MODULE_ALIAS("platform: omap-ocp2scp");
+MODULE_ALIAS("platform:omap-ocp2scp");
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("OMAP OCP2SCP driver");
 MODULE_LICENSE("GPL v2");
index 654f6f36a071c1411e21373d3cb53e00efadd4f6..55fe9020459f2c4bdcec710a90220b2ea32e54db 100644 (file)
@@ -412,18 +412,42 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
        return rv;
 }
 
-static void start_check_enables(struct smi_info *smi_info)
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+{
+       smi_info->last_timeout_jiffies = jiffies;
+       mod_timer(&smi_info->si_timer, new_val);
+       smi_info->timer_running = true;
+}
+
+/*
+ * Start a new message and (re)start the timer and thread.
+ */
+static void start_new_msg(struct smi_info *smi_info, unsigned char *msg,
+                         unsigned int size)
+{
+       smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
+
+       if (smi_info->thread)
+               wake_up_process(smi_info->thread);
+
+       smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
+}
+
+static void start_check_enables(struct smi_info *smi_info, bool start_timer)
 {
        unsigned char msg[2];
 
        msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
        msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
 
-       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
+       if (start_timer)
+               start_new_msg(smi_info, msg, 2);
+       else
+               smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
        smi_info->si_state = SI_CHECKING_ENABLES;
 }
 
-static void start_clear_flags(struct smi_info *smi_info)
+static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
 {
        unsigned char msg[3];
 
@@ -432,7 +456,10 @@ static void start_clear_flags(struct smi_info *smi_info)
        msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
        msg[2] = WDT_PRE_TIMEOUT_INT;
 
-       smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
+       if (start_timer)
+               start_new_msg(smi_info, msg, 3);
+       else
+               smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
        smi_info->si_state = SI_CLEARING_FLAGS;
 }
 
@@ -442,10 +469,8 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
        smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
        smi_info->curr_msg->data_size = 2;
 
-       smi_info->handlers->start_transaction(
-               smi_info->si_sm,
-               smi_info->curr_msg->data,
-               smi_info->curr_msg->data_size);
+       start_new_msg(smi_info, smi_info->curr_msg->data,
+                     smi_info->curr_msg->data_size);
        smi_info->si_state = SI_GETTING_MESSAGES;
 }
 
@@ -455,20 +480,11 @@ static void start_getting_events(struct smi_info *smi_info)
        smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
        smi_info->curr_msg->data_size = 2;
 
-       smi_info->handlers->start_transaction(
-               smi_info->si_sm,
-               smi_info->curr_msg->data,
-               smi_info->curr_msg->data_size);
+       start_new_msg(smi_info, smi_info->curr_msg->data,
+                     smi_info->curr_msg->data_size);
        smi_info->si_state = SI_GETTING_EVENTS;
 }
 
-static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
-{
-       smi_info->last_timeout_jiffies = jiffies;
-       mod_timer(&smi_info->si_timer, new_val);
-       smi_info->timer_running = true;
-}
-
 /*
  * When we have a situtaion where we run out of memory and cannot
  * allocate messages, we just leave them in the BMC and run the system
@@ -478,11 +494,11 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
  * Note that we cannot just use disable_irq(), since the interrupt may
  * be shared.
  */
-static inline bool disable_si_irq(struct smi_info *smi_info)
+static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer)
 {
        if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
                smi_info->interrupt_disabled = true;
-               start_check_enables(smi_info);
+               start_check_enables(smi_info, start_timer);
                return true;
        }
        return false;
@@ -492,7 +508,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info)
 {
        if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
                smi_info->interrupt_disabled = false;
-               start_check_enables(smi_info);
+               start_check_enables(smi_info, true);
                return true;
        }
        return false;
@@ -510,7 +526,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info)
 
        msg = ipmi_alloc_smi_msg();
        if (!msg) {
-               if (!disable_si_irq(smi_info))
+               if (!disable_si_irq(smi_info, true))
                        smi_info->si_state = SI_NORMAL;
        } else if (enable_si_irq(smi_info)) {
                ipmi_free_smi_msg(msg);
@@ -526,7 +542,7 @@ static void handle_flags(struct smi_info *smi_info)
                /* Watchdog pre-timeout */
                smi_inc_stat(smi_info, watchdog_pretimeouts);
 
-               start_clear_flags(smi_info);
+               start_clear_flags(smi_info, true);
                smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
                if (smi_info->intf)
                        ipmi_smi_watchdog_pretimeout(smi_info->intf);
@@ -879,8 +895,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
                        msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
                        msg[1] = IPMI_GET_MSG_FLAGS_CMD;
 
-                       smi_info->handlers->start_transaction(
-                               smi_info->si_sm, msg, 2);
+                       start_new_msg(smi_info, msg, 2);
                        smi_info->si_state = SI_GETTING_FLAGS;
                        goto restart;
                }
@@ -910,7 +925,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
                 * disable and messages disabled.
                 */
                if (smi_info->supports_event_msg_buff || smi_info->irq) {
-                       start_check_enables(smi_info);
+                       start_check_enables(smi_info, true);
                } else {
                        smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
                        if (!smi_info->curr_msg)
@@ -920,6 +935,13 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
                }
                goto restart;
        }
+
+       if (si_sm_result == SI_SM_IDLE && smi_info->timer_running) {
+               /* Ok it if fails, the timer will just go off. */
+               if (del_timer(&smi_info->si_timer))
+                       smi_info->timer_running = false;
+       }
+
  out:
        return si_sm_result;
 }
@@ -2560,6 +2582,7 @@ static const struct of_device_id of_ipmi_match[] = {
          .data = (void *)(unsigned long) SI_BT },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_ipmi_match);
 
 static int of_ipmi_probe(struct platform_device *dev)
 {
@@ -2646,7 +2669,6 @@ static int of_ipmi_probe(struct platform_device *dev)
        }
        return 0;
 }
-MODULE_DEVICE_TABLE(of, of_ipmi_match);
 #else
 #define of_ipmi_match NULL
 static int of_ipmi_probe(struct platform_device *dev)
@@ -3613,7 +3635,7 @@ static int try_smi_init(struct smi_info *new_smi)
         * Start clearing the flags before we enable interrupts or the
         * timer to avoid racing with the timer.
         */
-       start_clear_flags(new_smi);
+       start_clear_flags(new_smi, false);
 
        /*
         * IRQ is defined to be set when non-zero.  req_events will
@@ -3908,7 +3930,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
                poll(to_clean);
                schedule_timeout_uninterruptible(1);
        }
-       disable_si_irq(to_clean);
+       disable_si_irq(to_clean, false);
        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                poll(to_clean);
                schedule_timeout_uninterruptible(1);
index 0ac3bd1a5497c5bae41f1cc51ac8cdf667ed73b4..096f0cef4da14152653ea61daa010b367174759d 100644 (file)
@@ -153,6 +153,9 @@ static int timeout = 10;
 /* The pre-timeout is disabled by default. */
 static int pretimeout;
 
+/* Default timeout to set on panic */
+static int panic_wdt_timeout = 255;
+
 /* Default action is to reset the board on a timeout. */
 static unsigned char action_val = WDOG_TIMEOUT_RESET;
 
@@ -293,6 +296,9 @@ MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
 module_param(pretimeout, timeout, 0644);
 MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
 
+module_param(panic_wdt_timeout, timeout, 0644);
+MODULE_PARM_DESC(timeout, "Timeout value on kernel panic in seconds.");
+
 module_param_cb(action, &param_ops_str, action_op, 0644);
 MODULE_PARM_DESC(action, "Timeout action. One of: "
                 "reset, none, power_cycle, power_off.");
@@ -1189,7 +1195,7 @@ static int wdog_panic_handler(struct notifier_block *this,
                /* Make sure we do this only once. */
                panic_event_handled = 1;
 
-               timeout = 255;
+               timeout = panic_wdt_timeout;
                pretimeout = 0;
                panic_halt_ipmi_set_timeout();
        }
index f26b0ae23bea77719c5f6e13e9cfcc33d5706405..45cc39aabeeeb8fde7967971516a4efad50d2caa 100644 (file)
@@ -226,21 +226,23 @@ int tpm_chip_register(struct tpm_chip *chip)
        if (rc)
                goto out_err;
 
-       if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
-               rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
-                                                           &chip->dev.kobj,
-                                                           "ppi");
-               if (rc)
-                       goto out_err;
-       }
-
        /* Make the chip available. */
        spin_lock(&driver_lock);
-       list_add_rcu(&chip->list, &tpm_chip_list);
+       list_add_tail_rcu(&chip->list, &tpm_chip_list);
        spin_unlock(&driver_lock);
 
        chip->flags |= TPM_CHIP_FLAG_REGISTERED;
 
+       if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
+               rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
+                                                           &chip->dev.kobj,
+                                                           "ppi");
+               if (rc && rc != -ENOENT) {
+                       tpm_chip_unregister(chip);
+                       return rc;
+               }
+       }
+
        return 0;
 out_err:
        tpm1_chip_unregister(chip);
index bd7039fafa8aa7c34326e7a2270cd09e42837d81..c12130485fc18e966c9e41736e57bd7fd0586082 100644 (file)
@@ -443,12 +443,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
                             TPM_DIGEST_SIZE);
 
        /* sensitive */
-       tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len);
+       tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1);
 
        tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
        tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
-       tpm_buf_append_u16(&buf, payload->key_len);
+       tpm_buf_append_u16(&buf, payload->key_len + 1);
        tpm_buf_append(&buf, payload->key, payload->key_len);
+       tpm_buf_append_u8(&buf, payload->migratable);
 
        /* public */
        tpm_buf_append_u16(&buf, 14);
@@ -573,6 +574,8 @@ static int tpm2_unseal(struct tpm_chip *chip,
                       u32 blob_handle)
 {
        struct tpm_buf buf;
+       u16 data_len;
+       u8 *data;
        int rc;
 
        rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
@@ -591,11 +594,13 @@ static int tpm2_unseal(struct tpm_chip *chip,
                rc = -EPERM;
 
        if (!rc) {
-               payload->key_len = be16_to_cpup(
+               data_len = be16_to_cpup(
                        (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
+               data = &buf.data[TPM_HEADER_SIZE + 6];
 
-               memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6],
-                      payload->key_len);
+               memcpy(payload->key, data, data_len - 1);
+               payload->key_len = data_len - 1;
+               payload->migratable = data[data_len - 1];
        }
 
        tpm_buf_destroy(&buf);
index 1141456a4b1f1b974192e89574af9e165051922b..570f30c5c5f42ee5ee8076e17f45301de11ecf59 100644 (file)
@@ -53,17 +53,18 @@ int read_log(struct tpm_bios_log *log)
                goto cleanup_eio;
        }
 
-       of_node_put(np);
        log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
        if (!log->bios_event_log) {
                pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
                       __func__);
+               of_node_put(np);
                return -ENOMEM;
        }
 
        log->bios_event_log_end = log->bios_event_log + *sizep;
 
        memcpy(log->bios_event_log, __va(*basep), *sizep);
+       of_node_put(np);
 
        return 0;
 
index 696ef1d56b4f5830682bc1227b72686c2906eefb..65f7eecc45b01c489e2381b2311a95f2898527df 100644 (file)
@@ -645,6 +645,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
 {
        u32 vendor, intfcaps, intmask;
        int rc, i, irq_s, irq_e, probe;
+       int irq_r = -1;
        struct tpm_chip *chip;
        struct priv_data *priv;
 
@@ -751,6 +752,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
                irq_s =
                    ioread8(chip->vendor.iobase +
                            TPM_INT_VECTOR(chip->vendor.locality));
+               irq_r = irq_s;
                if (irq_s) {
                        irq_e = irq_s;
                } else {
@@ -805,6 +807,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
                        iowrite32(intmask,
                                  chip->vendor.iobase +
                                  TPM_INT_ENABLE(chip->vendor.locality));
+
+                       devm_free_irq(dev, i, chip);
                }
        }
        if (chip->vendor.irq) {
@@ -831,7 +835,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
                                  chip->vendor.iobase +
                                  TPM_INT_ENABLE(chip->vendor.locality));
                }
-       }
+       } else if (irq_r != -1)
+               iowrite8(irq_r, chip->vendor.iobase +
+                        TPM_INT_VECTOR(chip->vendor.locality));
 
        if (chip->flags & TPM_CHIP_FLAG_TPM2) {
                chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
index 1dd5d14d5dbe0f4cc6092ba535ef950440d323be..d71d01157dbb0ee0fe468db4f6f3156675936ce9 100644 (file)
@@ -19,6 +19,7 @@ static void __init h8300_div_clk_setup(struct device_node *node)
        const char *parent_name;
        void __iomem *divcr = NULL;
        int width;
+       int offset;
 
        num_parents = of_clk_get_parent_count(node);
        if (num_parents < 1) {
@@ -31,11 +32,14 @@ static void __init h8300_div_clk_setup(struct device_node *node)
                pr_err("%s: failed to map divide register", clk_name);
                goto error;
        }
+       offset = (unsigned long)divcr & 3;
+       offset = (3 - offset) * 8;
+       divcr = (void *)((unsigned long)divcr & ~3);
 
        parent_name = of_clk_get_parent_name(node, 0);
        of_property_read_u32(node, "renesas,width", &width);
        clk = clk_register_divider(NULL, clk_name, parent_name,
-                                  CLK_SET_RATE_GATE, divcr, 0, width,
+                                  CLK_SET_RATE_GATE, divcr, offset, width,
                                   CLK_DIVIDER_POWER_OF_TWO, &clklock);
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
index 71cfdf7c97086273b1cc8ae1235ecf919abcfda1..2eb5f0efae903cd5235bdd2132ec455dfafe7c26 100644 (file)
@@ -1,4 +1,5 @@
 menu "Clock Source drivers"
+       depends on !ARCH_USES_GETTIMEOFFSET
 
 config CLKSRC_OF
        bool
index 10202f1fdfd7b2afc6ccf9cd044cecdc2d3d66a7..517e1c7624d442f7de842fa011516415d86c66b3 100644 (file)
@@ -203,7 +203,7 @@ static int __init ftm_clockevent_init(unsigned long freq, int irq)
        int err;
 
        ftm_writel(0x00, priv->clkevt_base + FTM_CNTIN);
-       ftm_writel(~0UL, priv->clkevt_base + FTM_MOD);
+       ftm_writel(~0u, priv->clkevt_base + FTM_MOD);
 
        ftm_reset_counter(priv->clkevt_base);
 
@@ -230,7 +230,7 @@ static int __init ftm_clocksource_init(unsigned long freq)
        int err;
 
        ftm_writel(0x00, priv->clksrc_base + FTM_CNTIN);
-       ftm_writel(~0UL, priv->clksrc_base + FTM_MOD);
+       ftm_writel(~0u, priv->clksrc_base + FTM_MOD);
 
        ftm_reset_counter(priv->clksrc_base);
 
index 02a1945e5093f7c3c9efa83ee1af822ecc2b127d..89d3e4d7900c51f384f3b90200c1fecb2bab013f 100644 (file)
@@ -140,9 +140,10 @@ static cycle_t gic_hpt_read(struct clocksource *cs)
 }
 
 static struct clocksource gic_clocksource = {
-       .name   = "GIC",
-       .read   = gic_hpt_read,
-       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+       .name           = "GIC",
+       .read           = gic_hpt_read,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .archdata       = { .vdso_clock_mode = VDSO_CLOCK_GIC },
 };
 
 static void __init __gic_clocksource_init(void)
index 1582c1c016b098b7d40cccbaf52f7d715a0586d2..235a1ba73d92d577bbf605f5dab9d737fe246797 100644 (file)
@@ -84,6 +84,7 @@ config ARM_KIRKWOOD_CPUFREQ
 config ARM_MT8173_CPUFREQ
        bool "Mediatek MT8173 CPUFreq support"
        depends on ARCH_MEDIATEK && REGULATOR
+       depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST)
        depends on !CPU_THERMAL || THERMAL=y
        select PM_OPP
        help
@@ -201,7 +202,7 @@ config ARM_SA1110_CPUFREQ
 
 config ARM_SCPI_CPUFREQ
         tristate "SCPI based CPUfreq driver"
-       depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL
+       depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
         help
          This adds the CPUfreq driver support for ARM big.LITTLE platforms
          using SCPI protocol for CPU power management.
index adbd1de1cea55cbe6777d3a1c4dab546a6a68adf..c59bdcb83217071087cc0a90ef62e5cd01ce38d7 100644 (file)
@@ -5,7 +5,6 @@
 config X86_INTEL_PSTATE
        bool "Intel P state control"
        depends on X86
-       select ACPI_PROCESSOR if ACPI
        help
           This driver provides a P state for Intel core processors.
          The driver implements an internal governor and will become
index f1e42f8ce0fcc75a5e67ae4e5365d098d83cfc32..c5d256caa664a63731e0cb7db6f5b00e31c750d8 100644 (file)
@@ -149,6 +149,19 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
                        __func__, cpu, old_cluster, new_cluster, new_rate);
 
        ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
+       if (!ret) {
+               /*
+                * FIXME: clk_set_rate hasn't returned an error here however it
+                * may be that clk_change_rate failed due to hardware or
+                * firmware issues and wasn't able to report that due to the
+                * current design of the clk core layer. To work around this
+                * problem we will read back the clock rate and check it is
+                * correct. This needs to be removed once clk core is fixed.
+                */
+               if (clk_get_rate(clk[new_cluster]) != new_rate * 1000)
+                       ret = -EIO;
+       }
+
        if (WARN_ON(ret)) {
                pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
                                new_cluster);
@@ -189,15 +202,6 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
                mutex_unlock(&cluster_lock[old_cluster]);
        }
 
-       /*
-        * FIXME: clk_set_rate has to handle the case where clk_change_rate
-        * can fail due to hardware or firmware issues. Until the clk core
-        * layer is fixed, we can check here. In most of the cases we will
-        * be reading only the cached value anyway. This needs to  be removed
-        * once clk core is fixed.
-        */
-       if (bL_cpufreq_get_rate(cpu) != new_rate)
-               return -EIO;
        return 0;
 }
 
index 93c219fab850f7e268d46d1ff83a38f958963b26..7c0bdfb1a2ca47ea9dcd0b36ef892274edd929b4 100644 (file)
@@ -98,10 +98,11 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
        policy->max = cpu->perf_caps.highest_perf;
        policy->cpuinfo.min_freq = policy->min;
        policy->cpuinfo.max_freq = policy->max;
+       policy->shared_type = cpu->shared_type;
 
        if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
                cpumask_copy(policy->cpus, cpu->shared_cpu_map);
-       else {
+       else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) {
                /* Support only SW_ANY for now. */
                pr_debug("Unsupported CPU co-ord type\n");
                return -EFAULT;
@@ -166,8 +167,7 @@ static int __init cppc_cpufreq_init(void)
 
 out:
        for_each_possible_cpu(i)
-               if (all_cpu_data[i])
-                       kfree(all_cpu_data[i]);
+               kfree(all_cpu_data[i]);
 
        kfree(all_cpu_data);
        return -ENODEV;
index 7c48e7316d91e23cd8374852c477375ae65e1ccb..a83c995a62dfed9173823289d4cc3bbd3199cf12 100644 (file)
@@ -1401,13 +1401,10 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
        }
 
        cpumask_clear_cpu(cpu, policy->real_cpus);
+       remove_cpu_dev_symlink(policy, cpu);
 
-       if (cpumask_empty(policy->real_cpus)) {
+       if (cpumask_empty(policy->real_cpus))
                cpufreq_policy_free(policy, true);
-               return;
-       }
-
-       remove_cpu_dev_symlink(policy, cpu);
 }
 
 static void handle_update(struct work_struct *work)
index 11258c4c1b175be37827c201a8d7a422a5d3eda3..b260576ddb129c9bf485a12a954d0b1db30e08c5 100644 (file)
@@ -171,10 +171,6 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
 {
        int i;
 
-       mutex_lock(&cpufreq_governor_lock);
-       if (!policy->governor_enabled)
-               goto out_unlock;
-
        if (!all_cpus) {
                /*
                 * Use raw_smp_processor_id() to avoid preemptible warnings.
@@ -188,9 +184,6 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
                for_each_cpu(i, policy->cpus)
                        __gov_queue_work(i, dbs_data, delay);
        }
-
-out_unlock:
-       mutex_unlock(&cpufreq_governor_lock);
 }
 EXPORT_SYMBOL_GPL(gov_queue_work);
 
@@ -229,13 +222,24 @@ static void dbs_timer(struct work_struct *work)
        struct cpu_dbs_info *cdbs = container_of(work, struct cpu_dbs_info,
                                                 dwork.work);
        struct cpu_common_dbs_info *shared = cdbs->shared;
-       struct cpufreq_policy *policy = shared->policy;
-       struct dbs_data *dbs_data = policy->governor_data;
+       struct cpufreq_policy *policy;
+       struct dbs_data *dbs_data;
        unsigned int sampling_rate, delay;
        bool modify_all = true;
 
        mutex_lock(&shared->timer_mutex);
 
+       policy = shared->policy;
+
+       /*
+        * Governor might already be disabled and there is no point continuing
+        * with the work-handler.
+        */
+       if (!policy)
+               goto unlock;
+
+       dbs_data = policy->governor_data;
+
        if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
                struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 
@@ -252,6 +256,7 @@ static void dbs_timer(struct work_struct *work)
        delay = dbs_data->cdata->gov_dbs_timer(cdbs, dbs_data, modify_all);
        gov_queue_work(dbs_data, policy, delay, modify_all);
 
+unlock:
        mutex_unlock(&shared->timer_mutex);
 }
 
@@ -478,9 +483,17 @@ static int cpufreq_governor_stop(struct cpufreq_policy *policy,
        if (!shared || !shared->policy)
                return -EBUSY;
 
+       /*
+        * Work-handler must see this updated, as it should not proceed any
+        * further after governor is disabled. And so timer_mutex is taken while
+        * updating this value.
+        */
+       mutex_lock(&shared->timer_mutex);
+       shared->policy = NULL;
+       mutex_unlock(&shared->timer_mutex);
+
        gov_cancel_work(dbs_data, policy);
 
-       shared->policy = NULL;
        mutex_destroy(&shared->timer_mutex);
        return 0;
 }
index 93a3c635ea2741fa4296c013b564ec6a7c27b827..4d07cbd2b23cfb80ddc40fc0822ce37464991498 100644 (file)
 #include <asm/cpu_device_id.h>
 #include <asm/cpufeature.h>
 
-#if IS_ENABLED(CONFIG_ACPI)
-#include <acpi/processor.h>
-#endif
-
-#define BYT_RATIOS             0x66a
-#define BYT_VIDS               0x66b
-#define BYT_TURBO_RATIOS       0x66c
-#define BYT_TURBO_VIDS         0x66d
+#define ATOM_RATIOS            0x66a
+#define ATOM_VIDS              0x66b
+#define ATOM_TURBO_RATIOS      0x66c
+#define ATOM_TURBO_VIDS                0x66d
 
 #define FRAC_BITS 8
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
@@ -117,9 +113,6 @@ struct cpudata {
        u64     prev_mperf;
        u64     prev_tsc;
        struct sample sample;
-#if IS_ENABLED(CONFIG_ACPI)
-       struct acpi_processor_performance acpi_perf_data;
-#endif
 };
 
 static struct cpudata **all_cpu_data;
@@ -150,7 +143,6 @@ struct cpu_defaults {
 static struct pstate_adjust_policy pid_params;
 static struct pstate_funcs pstate_funcs;
 static int hwp_active;
-static int no_acpi_perf;
 
 struct perf_limits {
        int no_turbo;
@@ -163,8 +155,6 @@ struct perf_limits {
        int max_sysfs_pct;
        int min_policy_pct;
        int min_sysfs_pct;
-       int max_perf_ctl;
-       int min_perf_ctl;
 };
 
 static struct perf_limits performance_limits = {
@@ -191,8 +181,6 @@ static struct perf_limits powersave_limits = {
        .max_sysfs_pct = 100,
        .min_policy_pct = 0,
        .min_sysfs_pct = 0,
-       .max_perf_ctl = 0,
-       .min_perf_ctl = 0,
 };
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
@@ -201,153 +189,6 @@ static struct perf_limits *limits = &performance_limits;
 static struct perf_limits *limits = &powersave_limits;
 #endif
 
-#if IS_ENABLED(CONFIG_ACPI)
-/*
- * The max target pstate ratio is a 8 bit value in both PLATFORM_INFO MSR and
- * in TURBO_RATIO_LIMIT MSR, which pstate driver stores in max_pstate and
- * max_turbo_pstate fields. The PERF_CTL MSR contains 16 bit value for P state
- * ratio, out of it only high 8 bits are used. For example 0x1700 is setting
- * target ratio 0x17. The _PSS control value stores in a format which can be
- * directly written to PERF_CTL MSR. But in intel_pstate driver this shift
- * occurs during write to PERF_CTL (E.g. for cores core_set_pstate()).
- * This function converts the _PSS control value to intel pstate driver format
- * for comparison and assignment.
- */
-static int convert_to_native_pstate_format(struct cpudata *cpu, int index)
-{
-       return cpu->acpi_perf_data.states[index].control >> 8;
-}
-
-static int intel_pstate_init_perf_limits(struct cpufreq_policy *policy)
-{
-       struct cpudata *cpu;
-       int ret;
-       bool turbo_absent = false;
-       int max_pstate_index;
-       int min_pss_ctl, max_pss_ctl, turbo_pss_ctl;
-       int i;
-
-       cpu = all_cpu_data[policy->cpu];
-
-       pr_debug("intel_pstate: default limits 0x%x 0x%x 0x%x\n",
-                cpu->pstate.min_pstate, cpu->pstate.max_pstate,
-                cpu->pstate.turbo_pstate);
-
-       if (!cpu->acpi_perf_data.shared_cpu_map &&
-           zalloc_cpumask_var_node(&cpu->acpi_perf_data.shared_cpu_map,
-                                   GFP_KERNEL, cpu_to_node(policy->cpu))) {
-               return -ENOMEM;
-       }
-
-       ret = acpi_processor_register_performance(&cpu->acpi_perf_data,
-                                                 policy->cpu);
-       if (ret)
-               return ret;
-
-       /*
-        * Check if the control value in _PSS is for PERF_CTL MSR, which should
-        * guarantee that the states returned by it map to the states in our
-        * list directly.
-        */
-       if (cpu->acpi_perf_data.control_register.space_id !=
-                                               ACPI_ADR_SPACE_FIXED_HARDWARE)
-               return -EIO;
-
-       pr_debug("intel_pstate: CPU%u - ACPI _PSS perf data\n", policy->cpu);
-       for (i = 0; i < cpu->acpi_perf_data.state_count; i++)
-               pr_debug("     %cP%d: %u MHz, %u mW, 0x%x\n",
-                        (i == cpu->acpi_perf_data.state ? '*' : ' '), i,
-                        (u32) cpu->acpi_perf_data.states[i].core_frequency,
-                        (u32) cpu->acpi_perf_data.states[i].power,
-                        (u32) cpu->acpi_perf_data.states[i].control);
-
-       /*
-        * If there is only one entry _PSS, simply ignore _PSS and continue as
-        * usual without taking _PSS into account
-        */
-       if (cpu->acpi_perf_data.state_count < 2)
-               return 0;
-
-       turbo_pss_ctl = convert_to_native_pstate_format(cpu, 0);
-       min_pss_ctl = convert_to_native_pstate_format(cpu,
-                                       cpu->acpi_perf_data.state_count - 1);
-       /* Check if there is a turbo freq in _PSS */
-       if (turbo_pss_ctl <= cpu->pstate.max_pstate &&
-           turbo_pss_ctl > cpu->pstate.min_pstate) {
-               pr_debug("intel_pstate: no turbo range exists in _PSS\n");
-               limits->no_turbo = limits->turbo_disabled = 1;
-               cpu->pstate.turbo_pstate = cpu->pstate.max_pstate;
-               turbo_absent = true;
-       }
-
-       /* Check if the max non turbo p state < Intel P state max */
-       max_pstate_index = turbo_absent ? 0 : 1;
-       max_pss_ctl = convert_to_native_pstate_format(cpu, max_pstate_index);
-       if (max_pss_ctl < cpu->pstate.max_pstate &&
-           max_pss_ctl > cpu->pstate.min_pstate)
-               cpu->pstate.max_pstate = max_pss_ctl;
-
-       /* check If min perf > Intel P State min */
-       if (min_pss_ctl > cpu->pstate.min_pstate &&
-           min_pss_ctl < cpu->pstate.max_pstate) {
-               cpu->pstate.min_pstate = min_pss_ctl;
-               policy->cpuinfo.min_freq = min_pss_ctl * cpu->pstate.scaling;
-       }
-
-       if (turbo_absent)
-               policy->cpuinfo.max_freq = cpu->pstate.max_pstate *
-                                               cpu->pstate.scaling;
-       else {
-               policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate *
-                                               cpu->pstate.scaling;
-               /*
-                * The _PSS table doesn't contain whole turbo frequency range.
-                * This just contains +1 MHZ above the max non turbo frequency,
-                * with control value corresponding to max turbo ratio. But
-                * when cpufreq set policy is called, it will call with this
-                * max frequency, which will cause a reduced performance as
-                * this driver uses real max turbo frequency as the max
-                * frequeny. So correct this frequency in _PSS table to
-                * correct max turbo frequency based on the turbo ratio.
-                * Also need to convert to MHz as _PSS freq is in MHz.
-                */
-               cpu->acpi_perf_data.states[0].core_frequency =
-                                               turbo_pss_ctl * 100;
-       }
-
-       pr_debug("intel_pstate: Updated limits using _PSS 0x%x 0x%x 0x%x\n",
-                cpu->pstate.min_pstate, cpu->pstate.max_pstate,
-                cpu->pstate.turbo_pstate);
-       pr_debug("intel_pstate: policy max_freq=%d Khz min_freq = %d KHz\n",
-                policy->cpuinfo.max_freq, policy->cpuinfo.min_freq);
-
-       return 0;
-}
-
-static int intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
-{
-       struct cpudata *cpu;
-
-       if (!no_acpi_perf)
-               return 0;
-
-       cpu = all_cpu_data[policy->cpu];
-       acpi_processor_unregister_performance(policy->cpu);
-       return 0;
-}
-
-#else
-static int intel_pstate_init_perf_limits(struct cpufreq_policy *policy)
-{
-       return 0;
-}
-
-static int intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
-{
-       return 0;
-}
-#endif
-
 static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
                             int deadband, int integral) {
        pid->setpoint = setpoint;
@@ -684,36 +525,34 @@ static void __init intel_pstate_sysfs_expose_params(void)
 
 static void intel_pstate_hwp_enable(struct cpudata *cpudata)
 {
-       pr_info("intel_pstate: HWP enabled\n");
-
        wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
 }
 
-static int byt_get_min_pstate(void)
+static int atom_get_min_pstate(void)
 {
        u64 value;
 
-       rdmsrl(BYT_RATIOS, value);
+       rdmsrl(ATOM_RATIOS, value);
        return (value >> 8) & 0x7F;
 }
 
-static int byt_get_max_pstate(void)
+static int atom_get_max_pstate(void)
 {
        u64 value;
 
-       rdmsrl(BYT_RATIOS, value);
+       rdmsrl(ATOM_RATIOS, value);
        return (value >> 16) & 0x7F;
 }
 
-static int byt_get_turbo_pstate(void)
+static int atom_get_turbo_pstate(void)
 {
        u64 value;
 
-       rdmsrl(BYT_TURBO_RATIOS, value);
+       rdmsrl(ATOM_TURBO_RATIOS, value);
        return value & 0x7F;
 }
 
-static void byt_set_pstate(struct cpudata *cpudata, int pstate)
+static void atom_set_pstate(struct cpudata *cpudata, int pstate)
 {
        u64 val;
        int32_t vid_fp;
@@ -738,27 +577,42 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
        wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
 }
 
-#define BYT_BCLK_FREQS 5
-static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800};
-
-static int byt_get_scaling(void)
+static int silvermont_get_scaling(void)
 {
        u64 value;
        int i;
+       /* Defined in Table 35-6 from SDM (Sept 2015) */
+       static int silvermont_freq_table[] = {
+               83300, 100000, 133300, 116700, 80000};
 
        rdmsrl(MSR_FSB_FREQ, value);
-       i = value & 0x3;
+       i = value & 0x7;
+       WARN_ON(i > 4);
+
+       return silvermont_freq_table[i];
+}
 
-       BUG_ON(i > BYT_BCLK_FREQS);
+static int airmont_get_scaling(void)
+{
+       u64 value;
+       int i;
+       /* Defined in Table 35-10 from SDM (Sept 2015) */
+       static int airmont_freq_table[] = {
+               83300, 100000, 133300, 116700, 80000,
+               93300, 90000, 88900, 87500};
 
-       return byt_freq_table[i] * 100;
+       rdmsrl(MSR_FSB_FREQ, value);
+       i = value & 0xF;
+       WARN_ON(i > 8);
+
+       return airmont_freq_table[i];
 }
 
-static void byt_get_vid(struct cpudata *cpudata)
+static void atom_get_vid(struct cpudata *cpudata)
 {
        u64 value;
 
-       rdmsrl(BYT_VIDS, value);
+       rdmsrl(ATOM_VIDS, value);
        cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
        cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
        cpudata->vid.ratio = div_fp(
@@ -766,7 +620,7 @@ static void byt_get_vid(struct cpudata *cpudata)
                int_tofp(cpudata->pstate.max_pstate -
                        cpudata->pstate.min_pstate));
 
-       rdmsrl(BYT_TURBO_VIDS, value);
+       rdmsrl(ATOM_TURBO_VIDS, value);
        cpudata->vid.turbo = value & 0x7f;
 }
 
@@ -887,7 +741,7 @@ static struct cpu_defaults core_params = {
        },
 };
 
-static struct cpu_defaults byt_params = {
+static struct cpu_defaults silvermont_params = {
        .pid_policy = {
                .sample_rate_ms = 10,
                .deadband = 0,
@@ -897,13 +751,33 @@ static struct cpu_defaults byt_params = {
                .i_gain_pct = 4,
        },
        .funcs = {
-               .get_max = byt_get_max_pstate,
-               .get_max_physical = byt_get_max_pstate,
-               .get_min = byt_get_min_pstate,
-               .get_turbo = byt_get_turbo_pstate,
-               .set = byt_set_pstate,
-               .get_scaling = byt_get_scaling,
-               .get_vid = byt_get_vid,
+               .get_max = atom_get_max_pstate,
+               .get_max_physical = atom_get_max_pstate,
+               .get_min = atom_get_min_pstate,
+               .get_turbo = atom_get_turbo_pstate,
+               .set = atom_set_pstate,
+               .get_scaling = silvermont_get_scaling,
+               .get_vid = atom_get_vid,
+       },
+};
+
+static struct cpu_defaults airmont_params = {
+       .pid_policy = {
+               .sample_rate_ms = 10,
+               .deadband = 0,
+               .setpoint = 60,
+               .p_gain_pct = 14,
+               .d_gain_pct = 0,
+               .i_gain_pct = 4,
+       },
+       .funcs = {
+               .get_max = atom_get_max_pstate,
+               .get_max_physical = atom_get_max_pstate,
+               .get_min = atom_get_min_pstate,
+               .get_turbo = atom_get_turbo_pstate,
+               .set = atom_set_pstate,
+               .get_scaling = airmont_get_scaling,
+               .get_vid = atom_get_vid,
        },
 };
 
@@ -940,23 +814,12 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
         * policy, or by cpu specific default values determined through
         * experimentation.
         */
-       if (limits->max_perf_ctl && limits->max_sysfs_pct >=
-                                               limits->max_policy_pct) {
-               *max = limits->max_perf_ctl;
-       } else {
-               max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf),
-                                       limits->max_perf));
-               *max = clamp_t(int, max_perf_adj, cpu->pstate.min_pstate,
-                              cpu->pstate.turbo_pstate);
-       }
+       max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits->max_perf));
+       *max = clamp_t(int, max_perf_adj,
+                       cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
-       if (limits->min_perf_ctl) {
-               *min = limits->min_perf_ctl;
-       } else {
-               min_perf = fp_toint(mul_fp(int_tofp(max_perf),
-                                   limits->min_perf));
-               *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
-       }
+       min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits->min_perf));
+       *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
 }
 
 static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate, bool force)
@@ -1155,7 +1018,7 @@ static void intel_pstate_timer_func(unsigned long __data)
 static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x2a, core_params),
        ICPU(0x2d, core_params),
-       ICPU(0x37, byt_params),
+       ICPU(0x37, silvermont_params),
        ICPU(0x3a, core_params),
        ICPU(0x3c, core_params),
        ICPU(0x3d, core_params),
@@ -1164,7 +1027,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x45, core_params),
        ICPU(0x46, core_params),
        ICPU(0x47, core_params),
-       ICPU(0x4c, byt_params),
+       ICPU(0x4c, airmont_params),
        ICPU(0x4e, core_params),
        ICPU(0x4f, core_params),
        ICPU(0x5e, core_params),
@@ -1231,12 +1094,6 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
 
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
-#if IS_ENABLED(CONFIG_ACPI)
-       struct cpudata *cpu;
-       int i;
-#endif
-       pr_debug("intel_pstate: %s max %u policy->max %u\n", __func__,
-                policy->cpuinfo.max_freq, policy->max);
        if (!policy->cpuinfo.max_freq)
                return -ENODEV;
 
@@ -1244,6 +1101,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
            policy->max >= policy->cpuinfo.max_freq) {
                pr_debug("intel_pstate: set performance\n");
                limits = &performance_limits;
+               if (hwp_active)
+                       intel_pstate_hwp_set();
                return 0;
        }
 
@@ -1251,7 +1110,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        limits = &powersave_limits;
        limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
        limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
-       limits->max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
+       limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
+                                             policy->cpuinfo.max_freq);
        limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100);
 
        /* Normalize user input to [min_policy_pct, max_policy_pct] */
@@ -1263,6 +1123,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                                   limits->max_sysfs_pct);
        limits->max_perf_pct = max(limits->min_policy_pct,
                                   limits->max_perf_pct);
+       limits->max_perf = round_up(limits->max_perf, 8);
 
        /* Make sure min_perf_pct <= max_perf_pct */
        limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
@@ -1272,23 +1133,6 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
                                  int_tofp(100));
 
-#if IS_ENABLED(CONFIG_ACPI)
-       cpu = all_cpu_data[policy->cpu];
-       for (i = 0; i < cpu->acpi_perf_data.state_count; i++) {
-               int control;
-
-               control = convert_to_native_pstate_format(cpu, i);
-               if (control * cpu->pstate.scaling == policy->max)
-                       limits->max_perf_ctl = control;
-               if (control * cpu->pstate.scaling == policy->min)
-                       limits->min_perf_ctl = control;
-       }
-
-       pr_debug("intel_pstate: max %u policy_max %u perf_ctl [0x%x-0x%x]\n",
-                policy->cpuinfo.max_freq, policy->max, limits->min_perf_ctl,
-                limits->max_perf_ctl);
-#endif
-
        if (hwp_active)
                intel_pstate_hwp_set();
 
@@ -1343,30 +1187,18 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
        policy->cpuinfo.max_freq =
                cpu->pstate.turbo_pstate * cpu->pstate.scaling;
-       if (!no_acpi_perf)
-               intel_pstate_init_perf_limits(policy);
-       /*
-        * If there is no acpi perf data or error, we ignore and use Intel P
-        * state calculated limits, So this is not fatal error.
-        */
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
        cpumask_set_cpu(policy->cpu, policy->cpus);
 
        return 0;
 }
 
-static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
-{
-       return intel_pstate_exit_perf_limits(policy);
-}
-
 static struct cpufreq_driver intel_pstate_driver = {
        .flags          = CPUFREQ_CONST_LOOPS,
        .verify         = intel_pstate_verify_policy,
        .setpolicy      = intel_pstate_set_policy,
        .get            = intel_pstate_get,
        .init           = intel_pstate_cpu_init,
-       .exit           = intel_pstate_cpu_exit,
        .stop_cpu       = intel_pstate_stop_cpu,
        .name           = "intel_pstate",
 };
@@ -1408,6 +1240,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
 }
 
 #if IS_ENABLED(CONFIG_ACPI)
+#include <acpi/processor.h>
 
 static bool intel_pstate_no_acpi_pss(void)
 {
@@ -1557,8 +1390,10 @@ static int __init intel_pstate_init(void)
        if (!all_cpu_data)
                return -ENOMEM;
 
-       if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp)
+       if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) {
+               pr_info("intel_pstate: HWP enabled\n");
                hwp_active++;
+       }
 
        if (!hwp_active && hwp_only)
                goto out;
@@ -1593,15 +1428,14 @@ static int __init intel_pstate_setup(char *str)
 
        if (!strcmp(str, "disable"))
                no_load = 1;
-       if (!strcmp(str, "no_hwp"))
+       if (!strcmp(str, "no_hwp")) {
+               pr_info("intel_pstate: HWP disabled\n");
                no_hwp = 1;
+       }
        if (!strcmp(str, "force"))
                force_load = 1;
        if (!strcmp(str, "hwp_only"))
                hwp_only = 1;
-       if (!strcmp(str, "no_acpi"))
-               no_acpi_perf = 1;
-
        return 0;
 }
 early_param("intel_pstate", intel_pstate_setup);
index 9e231f52150c404ebd92e6d74ea6a24b5642576a..051a8a8224cd7ade8b846e62fc27d0733ba8f73b 100644 (file)
@@ -212,11 +212,11 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
        /* Find current DRAM frequency */
        tmp = s5pv210_dram_conf[ch].freq;
 
-       do_div(tmp, freq);
+       tmp /= freq;
 
        tmp1 = s5pv210_dram_conf[ch].refresh;
 
-       do_div(tmp1, tmp);
+       tmp1 /= tmp;
 
        __raw_writel(tmp1, reg);
 }
index 8b923b7e9389aabd96ee10350c0f0ea9f66556f6..01b50cb4c9822abb8455f0f465ed8587ef4d3ef5 100644 (file)
@@ -94,6 +94,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
        struct ccp_device *ccp;
        struct ccp_platform *ccp_platform;
        struct device *dev = &pdev->dev;
+       enum dev_dma_attr attr;
        struct resource *ior;
        int ret;
 
@@ -118,18 +119,24 @@ static int ccp_platform_probe(struct platform_device *pdev)
        }
        ccp->io_regs = ccp->io_map;
 
-       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
-       if (ret) {
-               dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
+       attr = device_get_dma_attr(dev);
+       if (attr == DEV_DMA_NOT_SUPPORTED) {
+               dev_err(dev, "DMA is not supported");
                goto e_err;
        }
 
-       ccp_platform->coherent = device_dma_is_coherent(ccp->dev);
+       ccp_platform->coherent = (attr == DEV_DMA_COHERENT);
        if (ccp_platform->coherent)
                ccp->axcache = CACHE_WB_NO_ALLOC;
        else
                ccp->axcache = CACHE_NONE;
 
+       ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+       if (ret) {
+               dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret);
+               goto e_err;
+       }
+
        dev_set_drvdata(dev, ccp);
 
        ret = ccp_init(ccp);
index 03856ad280b9349d650a0d06723a9f9da31e7c75..473d36d91644c2a00010d89dfc280d08c7ed343e 100644 (file)
@@ -198,7 +198,7 @@ static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
                        goto out_err;
                }
 
-               params_head = section_head->params;
+               params_head = section.params;
 
                while (params_head) {
                        if (copy_from_user(&key_val, (void __user *)params_head,
index 4e55239c7a307a61f84045d91b6966c4ad73aba1..53d22eb73b56a19884e6d8dea3c03bba245ebbc9 100644 (file)
@@ -729,8 +729,8 @@ atc_prep_dma_interleaved(struct dma_chan *chan,
                return NULL;
 
        dev_info(chan2dev(chan),
-                "%s: src=0x%08x, dest=0x%08x, numf=%d, frame_size=%d, flags=0x%lx\n",
-               __func__, xt->src_start, xt->dst_start, xt->numf,
+                "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
+               __func__, &xt->src_start, &xt->dst_start, xt->numf,
                xt->frame_size, flags);
 
        /*
@@ -824,8 +824,8 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
        u32                     ctrla;
        u32                     ctrlb;
 
-       dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d0x%x s0x%x l0x%zx f0x%lx\n",
-                       dest, src, len, flags);
+       dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n",
+                       &dest, &src, len, flags);
 
        if (unlikely(!len)) {
                dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
@@ -938,8 +938,8 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
        void __iomem            *vaddr;
        dma_addr_t              paddr;
 
-       dev_vdbg(chan2dev(chan), "%s: d0x%x v0x%x l0x%zx f0x%lx\n", __func__,
-               dest, value, len, flags);
+       dev_vdbg(chan2dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__,
+               &dest, value, len, flags);
 
        if (unlikely(!len)) {
                dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__);
@@ -1022,8 +1022,8 @@ atc_prep_dma_memset_sg(struct dma_chan *chan,
                dma_addr_t dest = sg_dma_address(sg);
                size_t len = sg_dma_len(sg);
 
-               dev_vdbg(chan2dev(chan), "%s: d0x%08x, l0x%zx\n",
-                        __func__, dest, len);
+               dev_vdbg(chan2dev(chan), "%s: d%pad, l0x%zx\n",
+                        __func__, &dest, len);
 
                if (!is_dma_fill_aligned(chan->device, dest, 0, len)) {
                        dev_err(chan2dev(chan), "%s: buffer is not aligned\n",
@@ -1439,9 +1439,9 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
        unsigned int            periods = buf_len / period_len;
        unsigned int            i;
 
-       dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@0x%08x - %d (%d/%d)\n",
+       dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%d/%d)\n",
                        direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE",
-                       buf_addr,
+                       &buf_addr,
                        periods, buf_len, period_len);
 
        if (unlikely(!atslave || !buf_len || !period_len)) {
index d1cfc8c876f933000c5708ae32af75007a774a2a..7f58f06157f6a35c9268b81472acb5ce8ea3aa87 100644 (file)
@@ -385,9 +385,9 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
 static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
 {
        dev_crit(chan2dev(&atchan->chan_common),
-                "  desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
-                lli->saddr, lli->daddr,
-                lli->ctrla, lli->ctrlb, lli->dscr);
+                "  desc: s%pad d%pad ctrl0x%x:0x%x l0x%pad\n",
+                &lli->saddr, &lli->daddr,
+                lli->ctrla, lli->ctrlb, &lli->dscr);
 }
 
 
index b5e132d4bae5b5f35d9b74cf8cd1f54bab8e20a6..7f039de143f0d07ba3e59cfcf6469082fdeef831 100644 (file)
@@ -920,8 +920,8 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan,
        desc->lld.mbr_cfg = chan_cc;
 
        dev_dbg(chan2dev(chan),
-               "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
-               __func__, desc->lld.mbr_sa, desc->lld.mbr_da,
+               "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+               __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da,
                desc->lld.mbr_ubc, desc->lld.mbr_cfg);
 
        /* Chain lld. */
@@ -953,8 +953,8 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
        if ((xt->numf > 1) && (xt->frame_size > 1))
                return NULL;
 
-       dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, numf=%d, frame_size=%d, flags=0x%lx\n",
-               __func__, xt->src_start, xt->dst_start, xt->numf,
+       dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, numf=%d, frame_size=%d, flags=0x%lx\n",
+               __func__, &xt->src_start, &xt->dst_start,       xt->numf,
                xt->frame_size, flags);
 
        src_addr = xt->src_start;
@@ -1179,8 +1179,8 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan,
        desc->lld.mbr_cfg = chan_cc;
 
        dev_dbg(chan2dev(chan),
-               "%s: lld: mbr_da=0x%08x, mbr_ds=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
-               __func__, desc->lld.mbr_da, desc->lld.mbr_ds, desc->lld.mbr_ubc,
+               "%s: lld: mbr_da=%pad, mbr_ds=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+               __func__, &desc->lld.mbr_da, &desc->lld.mbr_ds, desc->lld.mbr_ubc,
                desc->lld.mbr_cfg);
 
        return desc;
@@ -1193,8 +1193,8 @@ at_xdmac_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
        struct at_xdmac_chan    *atchan = to_at_xdmac_chan(chan);
        struct at_xdmac_desc    *desc;
 
-       dev_dbg(chan2dev(chan), "%s: dest=0x%08x, len=%d, pattern=0x%x, flags=0x%lx\n",
-               __func__, dest, len, value, flags);
+       dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n",
+               __func__, &dest, len, value, flags);
 
        if (unlikely(!len))
                return NULL;
@@ -1229,8 +1229,8 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
        /* Prepare descriptors. */
        for_each_sg(sgl, sg, sg_len, i) {
-               dev_dbg(chan2dev(chan), "%s: dest=0x%08x, len=%d, pattern=0x%x, flags=0x%lx\n",
-                       __func__, sg_dma_address(sg), sg_dma_len(sg),
+               dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n",
+                       __func__, &sg_dma_address(sg), sg_dma_len(sg),
                        value, flags);
                desc = at_xdmac_memset_create_desc(chan, atchan,
                                                   sg_dma_address(sg),
index 6b03e4e84e6bf29b2226359e2e60bb43cd1474ce..0675e268d5777967489bf25b30f5d217290fa441 100644 (file)
 
 /* CCCFG register */
 #define GET_NUM_DMACH(x)       (x & 0x7) /* bits 0-2 */
-#define GET_NUM_QDMACH(x)      (x & 0x70 >> 4) /* bits 4-6 */
+#define GET_NUM_QDMACH(x)      ((x & 0x70) >> 4) /* bits 4-6 */
 #define GET_NUM_PAENTRY(x)     ((x & 0x7000) >> 12) /* bits 12-14 */
 #define GET_NUM_EVQUE(x)       ((x & 0x70000) >> 16) /* bits 16-18 */
 #define GET_NUM_REGN(x)                ((x & 0x300000) >> 20) /* bits 20-21 */
@@ -1565,7 +1565,7 @@ static void edma_tc_set_pm_state(struct edma_tc *tc, bool enable)
        struct platform_device *tc_pdev;
        int ret;
 
-       if (!tc)
+       if (!IS_ENABLED(CONFIG_OF) || !tc)
                return;
 
        tc_pdev = of_find_device_by_node(tc->node);
index 7058d58ba5887b6711bf2fedef3cf70c19db83e5..0f6fd42f55ca41975b12dbe267ef3aabdb81c017 100644 (file)
@@ -1462,7 +1462,7 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
 
 #define EVENT_REMAP_CELLS 3
 
-static int __init sdma_event_remap(struct sdma_engine *sdma)
+static int sdma_event_remap(struct sdma_engine *sdma)
 {
        struct device_node *np = sdma->dev->of_node;
        struct device_node *gpr_np = of_parse_phandle(np, "gpr", 0);
index ebd8a5f398b08ee2bc883ccb06a7752657eb4877..f1bcc2a163b30cef09b3d682b399037e2b9268c3 100644 (file)
@@ -679,8 +679,11 @@ static int usb_dmac_runtime_suspend(struct device *dev)
        struct usb_dmac *dmac = dev_get_drvdata(dev);
        int i;
 
-       for (i = 0; i < dmac->n_channels; ++i)
+       for (i = 0; i < dmac->n_channels; ++i) {
+               if (!dmac->channels[i].iomem)
+                       break;
                usb_dmac_chan_halt(&dmac->channels[i]);
+       }
 
        return 0;
 }
@@ -799,11 +802,10 @@ static int usb_dmac_probe(struct platform_device *pdev)
        ret = pm_runtime_get_sync(&pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
-               return ret;
+               goto error_pm;
        }
 
        ret = usb_dmac_init(dmac);
-       pm_runtime_put(&pdev->dev);
 
        if (ret) {
                dev_err(&pdev->dev, "failed to reset device\n");
@@ -851,10 +853,13 @@ static int usb_dmac_probe(struct platform_device *pdev)
        if (ret < 0)
                goto error;
 
+       pm_runtime_put(&pdev->dev);
        return 0;
 
 error:
        of_dma_controller_free(pdev->dev.of_node);
+       pm_runtime_put(&pdev->dev);
+error_pm:
        pm_runtime_disable(&pdev->dev);
        return ret;
 }
index 615ce6d464fb8bbbe821e2e606534168122890fe..306f75700bf8e1fa5b5c6a7731645ad4a4d86f60 100644 (file)
@@ -389,7 +389,6 @@ struct amdgpu_clock {
  * Fences.
  */
 struct amdgpu_fence_driver {
-       struct amdgpu_ring              *ring;
        uint64_t                        gpu_addr;
        volatile uint32_t               *cpu_addr;
        /* sync_seq is protected by ring emission lock */
@@ -398,7 +397,7 @@ struct amdgpu_fence_driver {
        bool                            initialized;
        struct amdgpu_irq_src           *irq_src;
        unsigned                        irq_type;
-       struct delayed_work             lockup_work;
+       struct timer_list               fallback_timer;
        wait_queue_head_t               fence_queue;
 };
 
@@ -917,8 +916,8 @@ struct amdgpu_ring {
 #define AMDGPU_VM_FAULT_STOP_ALWAYS    2
 
 struct amdgpu_vm_pt {
-       struct amdgpu_bo                *bo;
-       uint64_t                        addr;
+       struct amdgpu_bo        *bo;
+       uint64_t                addr;
 };
 
 struct amdgpu_vm_id {
@@ -926,8 +925,6 @@ struct amdgpu_vm_id {
        uint64_t                pd_gpu_addr;
        /* last flushed PD/PT update */
        struct fence            *flushed_updates;
-       /* last use of vmid */
-       struct fence            *last_id_use;
 };
 
 struct amdgpu_vm {
@@ -957,24 +954,70 @@ struct amdgpu_vm {
 
        /* for id and flush management per ring */
        struct amdgpu_vm_id     ids[AMDGPU_MAX_RINGS];
+       /* for interval tree */
+       spinlock_t              it_lock;
 };
 
 struct amdgpu_vm_manager {
-       struct fence                    *active[AMDGPU_NUM_VM];
-       uint32_t                        max_pfn;
+       struct {
+               struct fence    *active;
+               atomic_long_t   owner;
+       } ids[AMDGPU_NUM_VM];
+
+       uint32_t                                max_pfn;
        /* number of VMIDs */
-       unsigned                        nvm;
+       unsigned                                nvm;
        /* vram base address for page table entry  */
-       u64                             vram_base_offset;
+       u64                                     vram_base_offset;
        /* is vm enabled? */
-       bool                            enabled;
-       /* for hw to save the PD addr on suspend/resume */
-       uint32_t                        saved_table_addr[AMDGPU_NUM_VM];
+       bool                                    enabled;
        /* vm pte handling */
        const struct amdgpu_vm_pte_funcs        *vm_pte_funcs;
        struct amdgpu_ring                      *vm_pte_funcs_ring;
 };
 
+void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
+                                              struct amdgpu_vm *vm,
+                                              struct list_head *head);
+int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
+                     struct amdgpu_sync *sync);
+void amdgpu_vm_flush(struct amdgpu_ring *ring,
+                    struct amdgpu_vm *vm,
+                    struct fence *updates);
+void amdgpu_vm_fence(struct amdgpu_device *adev,
+                    struct amdgpu_vm *vm,
+                    struct fence *fence);
+uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
+int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+                                   struct amdgpu_vm *vm);
+int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
+                         struct amdgpu_vm *vm);
+int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                            struct amdgpu_sync *sync);
+int amdgpu_vm_bo_update(struct amdgpu_device *adev,
+                       struct amdgpu_bo_va *bo_va,
+                       struct ttm_mem_reg *mem);
+void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
+                            struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
+                                      struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
+                                     struct amdgpu_vm *vm,
+                                     struct amdgpu_bo *bo);
+int amdgpu_vm_bo_map(struct amdgpu_device *adev,
+                    struct amdgpu_bo_va *bo_va,
+                    uint64_t addr, uint64_t offset,
+                    uint64_t size, uint32_t flags);
+int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
+                      struct amdgpu_bo_va *bo_va,
+                      uint64_t addr);
+void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
+                     struct amdgpu_bo_va *bo_va);
+int amdgpu_vm_free_job(struct amdgpu_job *job);
+
 /*
  * context related structures
  */
@@ -1211,6 +1254,7 @@ struct amdgpu_cs_parser {
        /* relocations */
        struct amdgpu_bo_list_entry     *vm_bos;
        struct list_head        validated;
+       struct fence            *fence;
 
        struct amdgpu_ib        *ibs;
        uint32_t                num_ibs;
@@ -1226,7 +1270,7 @@ struct amdgpu_job {
        struct amdgpu_device    *adev;
        struct amdgpu_ib        *ibs;
        uint32_t                num_ibs;
-       struct mutex            job_lock;
+       void                    *owner;
        struct amdgpu_user_fence uf;
        int (*free_job)(struct amdgpu_job *job);
 };
@@ -2257,11 +2301,6 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev);
 bool amdgpu_card_posted(struct amdgpu_device *adev);
 void amdgpu_update_display_priority(struct amdgpu_device *adev);
 bool amdgpu_boot_test_post_card(struct amdgpu_device *adev);
-struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
-                                                struct drm_file *filp,
-                                                struct amdgpu_ctx *ctx,
-                                                struct amdgpu_ib *ibs,
-                                                uint32_t num_ibs);
 
 int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
 int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
@@ -2318,49 +2357,6 @@ int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
 long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
                             unsigned long arg);
 
-/*
- * vm
- */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
-                                         struct amdgpu_vm *vm,
-                                         struct list_head *head);
-int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
-                     struct amdgpu_sync *sync);
-void amdgpu_vm_flush(struct amdgpu_ring *ring,
-                    struct amdgpu_vm *vm,
-                    struct fence *updates);
-void amdgpu_vm_fence(struct amdgpu_device *adev,
-                    struct amdgpu_vm *vm,
-                    struct amdgpu_fence *fence);
-uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
-int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
-                                   struct amdgpu_vm *vm);
-int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
-                               struct amdgpu_vm *vm);
-int amdgpu_vm_clear_invalids(struct amdgpu_device *adev,
-                               struct amdgpu_vm *vm, struct amdgpu_sync *sync);
-int amdgpu_vm_bo_update(struct amdgpu_device *adev,
-                       struct amdgpu_bo_va *bo_va,
-                       struct ttm_mem_reg *mem);
-void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
-                            struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
-                                      struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
-                                     struct amdgpu_vm *vm,
-                                     struct amdgpu_bo *bo);
-int amdgpu_vm_bo_map(struct amdgpu_device *adev,
-                    struct amdgpu_bo_va *bo_va,
-                    uint64_t addr, uint64_t offset,
-                    uint64_t size, uint32_t flags);
-int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
-                      struct amdgpu_bo_va *bo_va,
-                      uint64_t addr);
-void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
-                     struct amdgpu_bo_va *bo_va);
-int amdgpu_vm_free_job(struct amdgpu_job *job);
 /*
  * functions used by amdgpu_encoder.c
  */
index dfc4d02c7a38f21501c3c3af565989522bea3bb6..3afcf0237c25474c662f499d4583c7743f6067f9 100644 (file)
@@ -127,30 +127,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
        return 0;
 }
 
-struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
-                                               struct drm_file *filp,
-                                               struct amdgpu_ctx *ctx,
-                                               struct amdgpu_ib *ibs,
-                                               uint32_t num_ibs)
-{
-       struct amdgpu_cs_parser *parser;
-       int i;
-
-       parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL);
-       if (!parser)
-               return NULL;
-
-       parser->adev = adev;
-       parser->filp = filp;
-       parser->ctx = ctx;
-       parser->ibs = ibs;
-       parser->num_ibs = num_ibs;
-       for (i = 0; i < num_ibs; i++)
-               ibs[i].ctx = ctx;
-
-       return parser;
-}
-
 int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 {
        union drm_amdgpu_cs *cs = data;
@@ -463,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
        return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
 }
 
-static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
+/**
+ * cs_parser_fini() - clean parser states
+ * @parser:    parser structure holding parsing context.
+ * @error:     error number
+ *
+ * If error is set than unvalidate buffer, otherwise just free memory
+ * used by parsing context.
+ **/
+static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
 {
+       unsigned i;
+
        if (!error) {
                /* Sort the buffer list from the smallest to largest buffer,
                 * which affects the order of buffers in the LRU list.
@@ -479,17 +465,14 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err
                list_sort(NULL, &parser->validated, cmp_size_smaller_first);
 
                ttm_eu_fence_buffer_objects(&parser->ticket,
-                               &parser->validated,
-                               &parser->ibs[parser->num_ibs-1].fence->base);
+                                           &parser->validated,
+                                           parser->fence);
        } else if (backoff) {
                ttm_eu_backoff_reservation(&parser->ticket,
                                           &parser->validated);
        }
-}
+       fence_put(parser->fence);
 
-static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
-{
-       unsigned i;
        if (parser->ctx)
                amdgpu_ctx_put(parser->ctx);
        if (parser->bo_list)
@@ -499,31 +482,12 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
        for (i = 0; i < parser->nchunks; i++)
                drm_free_large(parser->chunks[i].kdata);
        kfree(parser->chunks);
-       if (!amdgpu_enable_scheduler)
-       {
-               if (parser->ibs)
-                       for (i = 0; i < parser->num_ibs; i++)
-                               amdgpu_ib_free(parser->adev, &parser->ibs[i]);
-               kfree(parser->ibs);
-               if (parser->uf.bo)
-                       drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
-       }
-
-       kfree(parser);
-}
-
-/**
- * cs_parser_fini() - clean parser states
- * @parser:    parser structure holding parsing context.
- * @error:     error number
- *
- * If error is set than unvalidate buffer, otherwise just free memory
- * used by parsing context.
- **/
-static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
-{
-       amdgpu_cs_parser_fini_early(parser, error, backoff);
-       amdgpu_cs_parser_fini_late(parser);
+       if (parser->ibs)
+               for (i = 0; i < parser->num_ibs; i++)
+                       amdgpu_ib_free(parser->adev, &parser->ibs[i]);
+       kfree(parser->ibs);
+       if (parser->uf.bo)
+               drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
 }
 
 static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
@@ -610,15 +574,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
        }
 
        r = amdgpu_bo_vm_update_pte(parser, vm);
-       if (r) {
-               goto out;
-       }
-       amdgpu_cs_sync_rings(parser);
-       if (!amdgpu_enable_scheduler)
-               r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
-                                      parser->filp);
+       if (!r)
+               amdgpu_cs_sync_rings(parser);
 
-out:
        return r;
 }
 
@@ -828,36 +786,36 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        union drm_amdgpu_cs *cs = data;
        struct amdgpu_fpriv *fpriv = filp->driver_priv;
        struct amdgpu_vm *vm = &fpriv->vm;
-       struct amdgpu_cs_parser *parser;
+       struct amdgpu_cs_parser parser = {};
        bool reserved_buffers = false;
        int i, r;
 
        if (!adev->accel_working)
                return -EBUSY;
 
-       parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
-       if (!parser)
-               return -ENOMEM;
-       r = amdgpu_cs_parser_init(parser, data);
+       parser.adev = adev;
+       parser.filp = filp;
+
+       r = amdgpu_cs_parser_init(&parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
-               amdgpu_cs_parser_fini(parser, r, false);
+               amdgpu_cs_parser_fini(&parser, r, false);
                r = amdgpu_cs_handle_lockup(adev, r);
                return r;
        }
        mutex_lock(&vm->mutex);
-       r = amdgpu_cs_parser_relocs(parser);
+       r = amdgpu_cs_parser_relocs(&parser);
        if (r == -ENOMEM)
                DRM_ERROR("Not enough memory for command submission!\n");
        else if (r && r != -ERESTARTSYS)
                DRM_ERROR("Failed to process the buffer list %d!\n", r);
        else if (!r) {
                reserved_buffers = true;
-               r = amdgpu_cs_ib_fill(adev, parser);
+               r = amdgpu_cs_ib_fill(adev, &parser);
        }
 
        if (!r) {
-               r = amdgpu_cs_dependencies(adev, parser);
+               r = amdgpu_cs_dependencies(adev, &parser);
                if (r)
                        DRM_ERROR("Failed in the dependencies handling %d!\n", r);
        }
@@ -865,62 +823,71 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r)
                goto out;
 
-       for (i = 0; i < parser->num_ibs; i++)
-               trace_amdgpu_cs(parser, i);
+       for (i = 0; i < parser.num_ibs; i++)
+               trace_amdgpu_cs(&parser, i);
 
-       r = amdgpu_cs_ib_vm_chunk(adev, parser);
+       r = amdgpu_cs_ib_vm_chunk(adev, &parser);
        if (r)
                goto out;
 
-       if (amdgpu_enable_scheduler && parser->num_ibs) {
+       if (amdgpu_enable_scheduler && parser.num_ibs) {
+               struct amdgpu_ring * ring = parser.ibs->ring;
+               struct amd_sched_fence *fence;
                struct amdgpu_job *job;
-               struct amdgpu_ring * ring =  parser->ibs->ring;
+
                job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
                if (!job) {
                        r = -ENOMEM;
                        goto out;
                }
+
                job->base.sched = &ring->sched;
-               job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
-               job->adev = parser->adev;
-               job->ibs = parser->ibs;
-               job->num_ibs = parser->num_ibs;
-               job->base.owner = parser->filp;
-               mutex_init(&job->job_lock);
+               job->base.s_entity = &parser.ctx->rings[ring->idx].entity;
+               job->adev = parser.adev;
+               job->owner = parser.filp;
+               job->free_job = amdgpu_cs_free_job;
+
+               job->ibs = parser.ibs;
+               job->num_ibs = parser.num_ibs;
+               parser.ibs = NULL;
+               parser.num_ibs = 0;
+
                if (job->ibs[job->num_ibs - 1].user) {
-                       memcpy(&job->uf,  &parser->uf,
-                              sizeof(struct amdgpu_user_fence));
+                       job->uf = parser.uf;
                        job->ibs[job->num_ibs - 1].user = &job->uf;
+                       parser.uf.bo = NULL;
                }
 
-               job->free_job = amdgpu_cs_free_job;
-               mutex_lock(&job->job_lock);
-               r = amd_sched_entity_push_job(&job->base);
-               if (r) {
-                       mutex_unlock(&job->job_lock);
+               fence = amd_sched_fence_create(job->base.s_entity,
+                                              parser.filp);
+               if (!fence) {
+                       r = -ENOMEM;
                        amdgpu_cs_free_job(job);
                        kfree(job);
                        goto out;
                }
-               cs->out.handle =
-                       amdgpu_ctx_add_fence(parser->ctx, ring,
-                                            &job->base.s_fence->base);
-               parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle;
+               job->base.s_fence = fence;
+               parser.fence = fence_get(&fence->base);
 
-               list_sort(NULL, &parser->validated, cmp_size_smaller_first);
-               ttm_eu_fence_buffer_objects(&parser->ticket,
-                               &parser->validated,
-                               &job->base.s_fence->base);
+               cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring,
+                                                     &fence->base);
+               job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
 
-               mutex_unlock(&job->job_lock);
-               amdgpu_cs_parser_fini_late(parser);
-               mutex_unlock(&vm->mutex);
-               return 0;
+               trace_amdgpu_cs_ioctl(job);
+               amd_sched_entity_push_job(&job->base);
+
+       } else {
+               struct amdgpu_fence *fence;
+
+               r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs,
+                                      parser.filp);
+               fence = parser.ibs[parser.num_ibs - 1].fence;
+               parser.fence = fence_get(&fence->base);
+               cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
        }
 
-       cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
 out:
-       amdgpu_cs_parser_fini(parser, r, reserved_buffers);
+       amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
        mutex_unlock(&vm->mutex);
        r = amdgpu_cs_handle_lockup(adev, r);
        return r;
index 257d72205bb5c247d17f6d4ec6a79ea868d8e16d..3671f9f220bd47617d0cd3761543cedcae581d5e 100644 (file)
@@ -47,6 +47,9 @@
  * that the the relevant GPU caches have been flushed.
  */
 
+static struct kmem_cache *amdgpu_fence_slab;
+static atomic_t amdgpu_fence_slab_ref = ATOMIC_INIT(0);
+
 /**
  * amdgpu_fence_write - write a fence value
  *
@@ -84,24 +87,6 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
        return seq;
 }
 
-/**
- * amdgpu_fence_schedule_check - schedule lockup check
- *
- * @ring: pointer to struct amdgpu_ring
- *
- * Queues a delayed work item to check for lockups.
- */
-static void amdgpu_fence_schedule_check(struct amdgpu_ring *ring)
-{
-       /*
-        * Do not reset the timer here with mod_delayed_work,
-        * this can livelock in an interaction with TTM delayed destroy.
-        */
-       queue_delayed_work(system_power_efficient_wq,
-               &ring->fence_drv.lockup_work,
-               AMDGPU_FENCE_JIFFIES_TIMEOUT);
-}
-
 /**
  * amdgpu_fence_emit - emit a fence on the requested ring
  *
@@ -118,7 +103,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
        struct amdgpu_device *adev = ring->adev;
 
        /* we are protected by the ring emission mutex */
-       *fence = kmalloc(sizeof(struct amdgpu_fence), GFP_KERNEL);
+       *fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
        if ((*fence) == NULL) {
                return -ENOMEM;
        }
@@ -132,10 +117,22 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
        amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
                               (*fence)->seq,
                               AMDGPU_FENCE_FLAG_INT);
-       trace_amdgpu_fence_emit(ring->adev->ddev, ring->idx, (*fence)->seq);
        return 0;
 }
 
+/**
+ * amdgpu_fence_schedule_fallback - schedule fallback check
+ *
+ * @ring: pointer to struct amdgpu_ring
+ *
+ * Start a timer as fallback to our interrupts.
+ */
+static void amdgpu_fence_schedule_fallback(struct amdgpu_ring *ring)
+{
+       mod_timer(&ring->fence_drv.fallback_timer,
+                 jiffies + AMDGPU_FENCE_JIFFIES_TIMEOUT);
+}
+
 /**
  * amdgpu_fence_activity - check for fence activity
  *
@@ -202,45 +199,38 @@ static bool amdgpu_fence_activity(struct amdgpu_ring *ring)
        } while (atomic64_xchg(&ring->fence_drv.last_seq, seq) > seq);
 
        if (seq < last_emitted)
-               amdgpu_fence_schedule_check(ring);
+               amdgpu_fence_schedule_fallback(ring);
 
        return wake;
 }
 
 /**
- * amdgpu_fence_check_lockup - check for hardware lockup
+ * amdgpu_fence_process - process a fence
  *
- * @work: delayed work item
+ * @adev: amdgpu_device pointer
+ * @ring: ring index the fence is associated with
  *
- * Checks for fence activity and if there is none probe
- * the hardware if a lockup occured.
+ * Checks the current fence value and wakes the fence queue
+ * if the sequence number has increased (all asics).
  */
-static void amdgpu_fence_check_lockup(struct work_struct *work)
+void amdgpu_fence_process(struct amdgpu_ring *ring)
 {
-       struct amdgpu_fence_driver *fence_drv;
-       struct amdgpu_ring *ring;
-
-       fence_drv = container_of(work, struct amdgpu_fence_driver,
-                               lockup_work.work);
-       ring = fence_drv->ring;
-
        if (amdgpu_fence_activity(ring))
                wake_up_all(&ring->fence_drv.fence_queue);
 }
 
 /**
- * amdgpu_fence_process - process a fence
+ * amdgpu_fence_fallback - fallback for hardware interrupts
  *
- * @adev: amdgpu_device pointer
- * @ring: ring index the fence is associated with
+ * @work: delayed work item
  *
- * Checks the current fence value and wakes the fence queue
- * if the sequence number has increased (all asics).
+ * Checks for fence activity.
  */
-void amdgpu_fence_process(struct amdgpu_ring *ring)
+static void amdgpu_fence_fallback(unsigned long arg)
 {
-       if (amdgpu_fence_activity(ring))
-               wake_up_all(&ring->fence_drv.fence_queue);
+       struct amdgpu_ring *ring = (void *)arg;
+
+       amdgpu_fence_process(ring);
 }
 
 /**
@@ -290,7 +280,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
        if (atomic64_read(&ring->fence_drv.last_seq) >= seq)
                return 0;
 
-       amdgpu_fence_schedule_check(ring);
+       amdgpu_fence_schedule_fallback(ring);
        wait_event(ring->fence_drv.fence_queue, (
                   (signaled = amdgpu_fence_seq_signaled(ring, seq))));
 
@@ -491,9 +481,8 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
        atomic64_set(&ring->fence_drv.last_seq, 0);
        ring->fence_drv.initialized = false;
 
-       INIT_DELAYED_WORK(&ring->fence_drv.lockup_work,
-                       amdgpu_fence_check_lockup);
-       ring->fence_drv.ring = ring;
+       setup_timer(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback,
+                   (unsigned long)ring);
 
        init_waitqueue_head(&ring->fence_drv.fence_queue);
 
@@ -536,6 +525,13 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
  */
 int amdgpu_fence_driver_init(struct amdgpu_device *adev)
 {
+       if (atomic_inc_return(&amdgpu_fence_slab_ref) == 1) {
+               amdgpu_fence_slab = kmem_cache_create(
+                       "amdgpu_fence", sizeof(struct amdgpu_fence), 0,
+                       SLAB_HWCACHE_ALIGN, NULL);
+               if (!amdgpu_fence_slab)
+                       return -ENOMEM;
+       }
        if (amdgpu_debugfs_fence_init(adev))
                dev_err(adev->dev, "fence debugfs file creation failed\n");
 
@@ -554,9 +550,12 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
 {
        int i, r;
 
+       if (atomic_dec_and_test(&amdgpu_fence_slab_ref))
+               kmem_cache_destroy(amdgpu_fence_slab);
        mutex_lock(&adev->ring_lock);
        for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
                struct amdgpu_ring *ring = adev->rings[i];
+
                if (!ring || !ring->fence_drv.initialized)
                        continue;
                r = amdgpu_fence_wait_empty(ring);
@@ -568,6 +567,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
                amdgpu_irq_put(adev, ring->fence_drv.irq_src,
                               ring->fence_drv.irq_type);
                amd_sched_fini(&ring->sched);
+               del_timer_sync(&ring->fence_drv.fallback_timer);
                ring->fence_drv.initialized = false;
        }
        mutex_unlock(&adev->ring_lock);
@@ -751,18 +751,25 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
        fence->fence_wake.func = amdgpu_fence_check_signaled;
        __add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
        fence_get(f);
-       amdgpu_fence_schedule_check(ring);
+       if (!timer_pending(&ring->fence_drv.fallback_timer))
+               amdgpu_fence_schedule_fallback(ring);
        FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
        return true;
 }
 
+static void amdgpu_fence_release(struct fence *f)
+{
+       struct amdgpu_fence *fence = to_amdgpu_fence(f);
+       kmem_cache_free(amdgpu_fence_slab, fence);
+}
+
 const struct fence_ops amdgpu_fence_ops = {
        .get_driver_name = amdgpu_fence_get_driver_name,
        .get_timeline_name = amdgpu_fence_get_timeline_name,
        .enable_signaling = amdgpu_fence_enable_signaling,
        .signaled = amdgpu_fence_is_signaled,
        .wait = fence_default_wait,
-       .release = NULL,
+       .release = amdgpu_fence_release,
 };
 
 /*
index 087332858853c81da5db0121af9254bdff1db1cb..00c5b580f56c6e512a6eaea107130b353c66bc93 100644 (file)
@@ -483,6 +483,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
                if (domain == AMDGPU_GEM_DOMAIN_CPU)
                        goto error_unreserve;
        }
+       r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
+       if (r)
+               goto error_unreserve;
 
        r = amdgpu_vm_clear_freed(adev, bo_va->vm);
        if (r)
@@ -512,6 +515,9 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
        struct amdgpu_fpriv *fpriv = filp->driver_priv;
        struct amdgpu_bo *rbo;
        struct amdgpu_bo_va *bo_va;
+       struct ttm_validate_buffer tv, tv_pd;
+       struct ww_acquire_ctx ticket;
+       struct list_head list, duplicates;
        uint32_t invalid_flags, va_flags = 0;
        int r = 0;
 
@@ -549,7 +555,18 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                return -ENOENT;
        mutex_lock(&fpriv->vm.mutex);
        rbo = gem_to_amdgpu_bo(gobj);
-       r = amdgpu_bo_reserve(rbo, false);
+       INIT_LIST_HEAD(&list);
+       INIT_LIST_HEAD(&duplicates);
+       tv.bo = &rbo->tbo;
+       tv.shared = true;
+       list_add(&tv.head, &list);
+
+       if (args->operation == AMDGPU_VA_OP_MAP) {
+               tv_pd.bo = &fpriv->vm.page_directory->tbo;
+               tv_pd.shared = true;
+               list_add(&tv_pd.head, &list);
+       }
+       r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
        if (r) {
                mutex_unlock(&fpriv->vm.mutex);
                drm_gem_object_unreference_unlocked(gobj);
@@ -558,7 +575,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 
        bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo);
        if (!bo_va) {
-               amdgpu_bo_unreserve(rbo);
+               ttm_eu_backoff_reservation(&ticket, &list);
+               drm_gem_object_unreference_unlocked(gobj);
                mutex_unlock(&fpriv->vm.mutex);
                return -ENOENT;
        }
@@ -581,7 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
        default:
                break;
        }
-
+       ttm_eu_backoff_reservation(&ticket, &list);
        if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
                amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
        mutex_unlock(&fpriv->vm.mutex);
index e65987743871b18bb521113d86e0245c50686b57..9e25edafa7210000d1bfad1959f82725228e91df 100644 (file)
@@ -62,7 +62,7 @@ int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm,
        int r;
 
        if (size) {
-               r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
+               r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
                                      &ib->sa_bo, size, 256);
                if (r) {
                        dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
@@ -216,7 +216,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
        }
 
        if (ib->vm)
-               amdgpu_vm_fence(adev, ib->vm, ib->fence);
+               amdgpu_vm_fence(adev, ib->vm, &ib->fence->base);
 
        amdgpu_ring_unlock_commit(ring);
        return 0;
index 3c2ff4567798e1675adfb7a4563e4bd8931f0565..ea756e77b0232bcc131a90258b4ea454e1bc92e1 100644 (file)
@@ -189,10 +189,9 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
                                      struct amdgpu_sa_manager *sa_manager);
 int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
                                        struct amdgpu_sa_manager *sa_manager);
-int amdgpu_sa_bo_new(struct amdgpu_device *adev,
-                           struct amdgpu_sa_manager *sa_manager,
-                           struct amdgpu_sa_bo **sa_bo,
-                           unsigned size, unsigned align);
+int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
+                    struct amdgpu_sa_bo **sa_bo,
+                    unsigned size, unsigned align);
 void amdgpu_sa_bo_free(struct amdgpu_device *adev,
                              struct amdgpu_sa_bo **sa_bo,
                              struct fence *fence);
index 0212b31dc194ba542f8f009113d15c027aba0026..8b88edb0434bfb43ed4b7aae7e6f3e7dc63d0893 100644 (file)
@@ -311,8 +311,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
        return false;
 }
 
-int amdgpu_sa_bo_new(struct amdgpu_device *adev,
-                    struct amdgpu_sa_manager *sa_manager,
+int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
                     struct amdgpu_sa_bo **sa_bo,
                     unsigned size, unsigned align)
 {
index dcf4a8aca680d885fc6a52414ca2c8e5e3bd0914..438c05254695586bb95a9e3caa2ea356aa4b941f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/sched.h>
 #include <drm/drmP.h>
 #include "amdgpu.h"
+#include "amdgpu_trace.h"
 
 static struct fence *amdgpu_sched_dependency(struct amd_sched_job *sched_job)
 {
@@ -44,11 +45,8 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
                return NULL;
        }
        job = to_amdgpu_job(sched_job);
-       mutex_lock(&job->job_lock);
-       r = amdgpu_ib_schedule(job->adev,
-                              job->num_ibs,
-                              job->ibs,
-                              job->base.owner);
+       trace_amdgpu_sched_run_job(job);
+       r = amdgpu_ib_schedule(job->adev, job->num_ibs, job->ibs, job->owner);
        if (r) {
                DRM_ERROR("Error scheduling IBs (%d)\n", r);
                goto err;
@@ -61,8 +59,6 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
        if (job->free_job)
                job->free_job(job);
 
-       mutex_unlock(&job->job_lock);
-       fence_put(&job->base.s_fence->base);
        kfree(job);
        return fence ? &fence->base : NULL;
 }
@@ -88,21 +84,19 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
                        return -ENOMEM;
                job->base.sched = &ring->sched;
                job->base.s_entity = &adev->kernel_ctx.rings[ring->idx].entity;
+               job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner);
+               if (!job->base.s_fence) {
+                       kfree(job);
+                       return -ENOMEM;
+               }
+               *f = fence_get(&job->base.s_fence->base);
+
                job->adev = adev;
                job->ibs = ibs;
                job->num_ibs = num_ibs;
-               job->base.owner = owner;
-               mutex_init(&job->job_lock);
+               job->owner = owner;
                job->free_job = free_job;
-               mutex_lock(&job->job_lock);
-               r = amd_sched_entity_push_job(&job->base);
-               if (r) {
-                       mutex_unlock(&job->job_lock);
-                       kfree(job);
-                       return r;
-               }
-               *f = fence_get(&job->base.s_fence->base);
-               mutex_unlock(&job->job_lock);
+               amd_sched_entity_push_job(&job->base);
        } else {
                r = amdgpu_ib_schedule(adev, num_ibs, ibs, owner);
                if (r)
index ff3ca52ec6fe5543ea85ed4a31e2c2dc2538a83f..1caaf201b708a0487db721fc5bb9b341370d26df 100644 (file)
@@ -40,7 +40,7 @@ int amdgpu_semaphore_create(struct amdgpu_device *adev,
        if (*semaphore == NULL) {
                return -ENOMEM;
        }
-       r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
+       r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
                             &(*semaphore)->sa_bo, 8, 8);
        if (r) {
                kfree(*semaphore);
index a6697fd0521713cd9f60cbd7a2508b02e954b470..dd005c336c974ad708827c25edc4a4534772bb2c 100644 (file)
@@ -302,8 +302,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
                        return -EINVAL;
                }
 
-               if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores ||
-                   (count >= AMDGPU_NUM_SYNCS)) {
+               if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
+                       r = fence_wait(&fence->base, true);
+                       if (r)
+                               return r;
+                       continue;
+               }
+
+               if (count >= AMDGPU_NUM_SYNCS) {
                        /* not enough room, wait manually */
                        r = fence_wait(&fence->base, false);
                        if (r)
index 76ecbaf72a2e81bf70d12f63c1ca9c7517fdf3e6..8f9834ab1bd5a6ad2e0908dfeb0aa6ff5206fc31 100644 (file)
@@ -48,6 +48,57 @@ TRACE_EVENT(amdgpu_cs,
                      __entry->fences)
 );
 
+TRACE_EVENT(amdgpu_cs_ioctl,
+           TP_PROTO(struct amdgpu_job *job),
+           TP_ARGS(job),
+           TP_STRUCT__entry(
+                            __field(struct amdgpu_device *, adev)
+                            __field(struct amd_sched_job *, sched_job)
+                            __field(struct amdgpu_ib *, ib)
+                            __field(struct fence *, fence)
+                            __field(char *, ring_name)
+                            __field(u32, num_ibs)
+                            ),
+
+           TP_fast_assign(
+                          __entry->adev = job->adev;
+                          __entry->sched_job = &job->base;
+                          __entry->ib = job->ibs;
+                          __entry->fence = &job->base.s_fence->base;
+                          __entry->ring_name = job->ibs[0].ring->name;
+                          __entry->num_ibs = job->num_ibs;
+                          ),
+           TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
+                     __entry->adev, __entry->sched_job, __entry->ib,
+                     __entry->fence, __entry->ring_name, __entry->num_ibs)
+);
+
+TRACE_EVENT(amdgpu_sched_run_job,
+           TP_PROTO(struct amdgpu_job *job),
+           TP_ARGS(job),
+           TP_STRUCT__entry(
+                            __field(struct amdgpu_device *, adev)
+                            __field(struct amd_sched_job *, sched_job)
+                            __field(struct amdgpu_ib *, ib)
+                            __field(struct fence *, fence)
+                            __field(char *, ring_name)
+                            __field(u32, num_ibs)
+                            ),
+
+           TP_fast_assign(
+                          __entry->adev = job->adev;
+                          __entry->sched_job = &job->base;
+                          __entry->ib = job->ibs;
+                          __entry->fence = &job->base.s_fence->base;
+                          __entry->ring_name = job->ibs[0].ring->name;
+                          __entry->num_ibs = job->num_ibs;
+                          ),
+           TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
+                     __entry->adev, __entry->sched_job, __entry->ib,
+                     __entry->fence, __entry->ring_name, __entry->num_ibs)
+);
+
+
 TRACE_EVENT(amdgpu_vm_grab_id,
            TP_PROTO(unsigned vmid, int ring),
            TP_ARGS(vmid, ring),
@@ -196,49 +247,6 @@ TRACE_EVENT(amdgpu_bo_list_set,
            TP_printk("list=%p, bo=%p", __entry->list, __entry->bo)
 );
 
-DECLARE_EVENT_CLASS(amdgpu_fence_request,
-
-           TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
-           TP_ARGS(dev, ring, seqno),
-
-           TP_STRUCT__entry(
-                            __field(u32, dev)
-                            __field(int, ring)
-                            __field(u32, seqno)
-                            ),
-
-           TP_fast_assign(
-                          __entry->dev = dev->primary->index;
-                          __entry->ring = ring;
-                          __entry->seqno = seqno;
-                          ),
-
-           TP_printk("dev=%u, ring=%d, seqno=%u",
-                     __entry->dev, __entry->ring, __entry->seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_emit,
-
-           TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
-           TP_ARGS(dev, ring, seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_begin,
-
-           TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
-           TP_ARGS(dev, ring, seqno)
-);
-
-DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_end,
-
-           TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
-
-           TP_ARGS(dev, ring, seqno)
-);
-
 DECLARE_EVENT_CLASS(amdgpu_semaphore_request,
 
            TP_PROTO(int ring, struct amdgpu_semaphore *sem),
index 81bb8e9fc26dc2accddd19355d81461712420ef8..d4bac5f49939e1a780e5897754779fde9d1733d6 100644 (file)
@@ -1073,10 +1073,10 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
        ret = drm_mm_dump_table(m, mm);
        spin_unlock(&glob->lru_lock);
        if (ttm_pl == TTM_PL_VRAM)
-               seq_printf(m, "man size:%llu pages, ram usage:%luMB, vis usage:%luMB\n",
+               seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
                           adev->mman.bdev.man[ttm_pl].size,
-                          atomic64_read(&adev->vram_usage) >> 20,
-                          atomic64_read(&adev->vram_vis_usage) >> 20);
+                          (u64)atomic64_read(&adev->vram_usage) >> 20,
+                          (u64)atomic64_read(&adev->vram_vis_usage) >> 20);
        return ret;
 }
 
index 633a32a48560ec448a90475797fd1652b589dee7..159ce54bbd8d42137b1b47a4797b88aec3a6fd5e 100644 (file)
@@ -143,10 +143,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
        unsigned i;
 
        /* check if the id is still valid */
-       if (vm_id->id && vm_id->last_id_use &&
-           vm_id->last_id_use == adev->vm_manager.active[vm_id->id]) {
-               trace_amdgpu_vm_grab_id(vm_id->id, ring->idx);
-               return 0;
+       if (vm_id->id) {
+               unsigned id = vm_id->id;
+               long owner;
+
+               owner = atomic_long_read(&adev->vm_manager.ids[id].owner);
+               if (owner == (long)vm) {
+                       trace_amdgpu_vm_grab_id(vm_id->id, ring->idx);
+                       return 0;
+               }
        }
 
        /* we definately need to flush */
@@ -154,7 +159,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
 
        /* skip over VMID 0, since it is the system VM */
        for (i = 1; i < adev->vm_manager.nvm; ++i) {
-               struct fence *fence = adev->vm_manager.active[i];
+               struct fence *fence = adev->vm_manager.ids[i].active;
                struct amdgpu_ring *fring;
 
                if (fence == NULL) {
@@ -176,7 +181,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                if (choices[i]) {
                        struct fence *fence;
 
-                       fence  = adev->vm_manager.active[choices[i]];
+                       fence  = adev->vm_manager.ids[choices[i]].active;
                        vm_id->id = choices[i];
 
                        trace_amdgpu_vm_grab_id(choices[i], ring->idx);
@@ -207,24 +212,21 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
        uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
        struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx];
        struct fence *flushed_updates = vm_id->flushed_updates;
-       bool is_earlier = false;
-
-       if (flushed_updates && updates) {
-               BUG_ON(flushed_updates->context != updates->context);
-               is_earlier = (updates->seqno - flushed_updates->seqno <=
-                             INT_MAX) ? true : false;
-       }
+       bool is_later;
 
-       if (pd_addr != vm_id->pd_gpu_addr || !flushed_updates ||
-           is_earlier) {
+       if (!flushed_updates)
+               is_later = true;
+       else if (!updates)
+               is_later = false;
+       else
+               is_later = fence_is_later(updates, flushed_updates);
 
+       if (pd_addr != vm_id->pd_gpu_addr || is_later) {
                trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id);
-               if (is_earlier) {
+               if (is_later) {
                        vm_id->flushed_updates = fence_get(updates);
                        fence_put(flushed_updates);
                }
-               if (!flushed_updates)
-                       vm_id->flushed_updates = fence_get(updates);
                vm_id->pd_gpu_addr = pd_addr;
                amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr);
        }
@@ -244,16 +246,14 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
  */
 void amdgpu_vm_fence(struct amdgpu_device *adev,
                     struct amdgpu_vm *vm,
-                    struct amdgpu_fence *fence)
+                    struct fence *fence)
 {
-       unsigned ridx = fence->ring->idx;
-       unsigned vm_id = vm->ids[ridx].id;
-
-       fence_put(adev->vm_manager.active[vm_id]);
-       adev->vm_manager.active[vm_id] = fence_get(&fence->base);
+       struct amdgpu_ring *ring = amdgpu_ring_from_fence(fence);
+       unsigned vm_id = vm->ids[ring->idx].id;
 
-       fence_put(vm->ids[ridx].last_id_use);
-       vm->ids[ridx].last_id_use = fence_get(&fence->base);
+       fence_put(adev->vm_manager.ids[vm_id].active);
+       adev->vm_manager.ids[vm_id].active = fence_get(fence);
+       atomic_long_set(&adev->vm_manager.ids[vm_id].owner, (long)vm);
 }
 
 /**
@@ -332,6 +332,8 @@ int amdgpu_vm_free_job(struct amdgpu_job *job)
  *
  * @adev: amdgpu_device pointer
  * @bo: bo to clear
+ *
+ * need to reserve bo first before calling it.
  */
 static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
                              struct amdgpu_bo *bo)
@@ -343,24 +345,20 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
        uint64_t addr;
        int r;
 
-       r = amdgpu_bo_reserve(bo, false);
-       if (r)
-               return r;
-
        r = reservation_object_reserve_shared(bo->tbo.resv);
        if (r)
                return r;
 
        r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
        if (r)
-               goto error_unreserve;
+               goto error;
 
        addr = amdgpu_bo_gpu_offset(bo);
        entries = amdgpu_bo_size(bo) / 8;
 
        ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL);
        if (!ib)
-               goto error_unreserve;
+               goto error;
 
        r = amdgpu_ib_get(ring, NULL, entries * 2 + 64, ib);
        if (r)
@@ -378,16 +376,14 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
        if (!r)
                amdgpu_bo_fence(bo, fence, true);
        fence_put(fence);
-       if (amdgpu_enable_scheduler) {
-               amdgpu_bo_unreserve(bo);
+       if (amdgpu_enable_scheduler)
                return 0;
-       }
+
 error_free:
        amdgpu_ib_free(adev, ib);
        kfree(ib);
 
-error_unreserve:
-       amdgpu_bo_unreserve(bo);
+error:
        return r;
 }
 
@@ -989,7 +985,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
  * Add a mapping of the BO at the specefied addr into the VM.
  * Returns 0 for success, error for failure.
  *
- * Object has to be reserved and gets unreserved by this function!
+ * Object has to be reserved and unreserved outside!
  */
 int amdgpu_vm_bo_map(struct amdgpu_device *adev,
                     struct amdgpu_bo_va *bo_va,
@@ -1005,30 +1001,27 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
 
        /* validate the parameters */
        if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
-           size == 0 || size & AMDGPU_GPU_PAGE_MASK) {
-               amdgpu_bo_unreserve(bo_va->bo);
+           size == 0 || size & AMDGPU_GPU_PAGE_MASK)
                return -EINVAL;
-       }
 
        /* make sure object fit at this offset */
        eaddr = saddr + size;
-       if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo))) {
-               amdgpu_bo_unreserve(bo_va->bo);
+       if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
                return -EINVAL;
-       }
 
        last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
        if (last_pfn > adev->vm_manager.max_pfn) {
                dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
                        last_pfn, adev->vm_manager.max_pfn);
-               amdgpu_bo_unreserve(bo_va->bo);
                return -EINVAL;
        }
 
        saddr /= AMDGPU_GPU_PAGE_SIZE;
        eaddr /= AMDGPU_GPU_PAGE_SIZE;
 
+       spin_lock(&vm->it_lock);
        it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
+       spin_unlock(&vm->it_lock);
        if (it) {
                struct amdgpu_bo_va_mapping *tmp;
                tmp = container_of(it, struct amdgpu_bo_va_mapping, it);
@@ -1036,14 +1029,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
                dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with "
                        "0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr,
                        tmp->it.start, tmp->it.last + 1);
-               amdgpu_bo_unreserve(bo_va->bo);
                r = -EINVAL;
                goto error;
        }
 
        mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
        if (!mapping) {
-               amdgpu_bo_unreserve(bo_va->bo);
                r = -ENOMEM;
                goto error;
        }
@@ -1055,7 +1046,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
        mapping->flags = flags;
 
        list_add(&mapping->list, &bo_va->invalids);
+       spin_lock(&vm->it_lock);
        interval_tree_insert(&mapping->it, &vm->va);
+       spin_unlock(&vm->it_lock);
        trace_amdgpu_vm_bo_map(bo_va, mapping);
 
        /* Make sure the page tables are allocated */
@@ -1067,8 +1060,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
        if (eaddr > vm->max_pde_used)
                vm->max_pde_used = eaddr;
 
-       amdgpu_bo_unreserve(bo_va->bo);
-
        /* walk over the address space and allocate the page tables */
        for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
                struct reservation_object *resv = vm->page_directory->tbo.resv;
@@ -1077,13 +1068,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
                if (vm->page_tables[pt_idx].bo)
                        continue;
 
-               ww_mutex_lock(&resv->lock, NULL);
                r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
                                     AMDGPU_GPU_PAGE_SIZE, true,
                                     AMDGPU_GEM_DOMAIN_VRAM,
                                     AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
                                     NULL, resv, &pt);
-               ww_mutex_unlock(&resv->lock);
                if (r)
                        goto error_free;
 
@@ -1101,7 +1090,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
 
 error_free:
        list_del(&mapping->list);
+       spin_lock(&vm->it_lock);
        interval_tree_remove(&mapping->it, &vm->va);
+       spin_unlock(&vm->it_lock);
        trace_amdgpu_vm_bo_unmap(bo_va, mapping);
        kfree(mapping);
 
@@ -1119,7 +1110,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
  * Remove a mapping of the BO at the specefied addr from the VM.
  * Returns 0 for success, error for failure.
  *
- * Object has to be reserved and gets unreserved by this function!
+ * Object has to be reserved and unreserved outside!
  */
 int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
                       struct amdgpu_bo_va *bo_va,
@@ -1144,21 +1135,20 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
                                break;
                }
 
-               if (&mapping->list == &bo_va->invalids) {
-                       amdgpu_bo_unreserve(bo_va->bo);
+               if (&mapping->list == &bo_va->invalids)
                        return -ENOENT;
-               }
        }
 
        list_del(&mapping->list);
+       spin_lock(&vm->it_lock);
        interval_tree_remove(&mapping->it, &vm->va);
+       spin_unlock(&vm->it_lock);
        trace_amdgpu_vm_bo_unmap(bo_va, mapping);
 
        if (valid)
                list_add(&mapping->list, &vm->freed);
        else
                kfree(mapping);
-       amdgpu_bo_unreserve(bo_va->bo);
 
        return 0;
 }
@@ -1187,13 +1177,17 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
 
        list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
                list_del(&mapping->list);
+               spin_lock(&vm->it_lock);
                interval_tree_remove(&mapping->it, &vm->va);
+               spin_unlock(&vm->it_lock);
                trace_amdgpu_vm_bo_unmap(bo_va, mapping);
                list_add(&mapping->list, &vm->freed);
        }
        list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) {
                list_del(&mapping->list);
+               spin_lock(&vm->it_lock);
                interval_tree_remove(&mapping->it, &vm->va);
+               spin_unlock(&vm->it_lock);
                kfree(mapping);
        }
 
@@ -1241,7 +1235,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                vm->ids[i].id = 0;
                vm->ids[i].flushed_updates = NULL;
-               vm->ids[i].last_id_use = NULL;
        }
        mutex_init(&vm->mutex);
        vm->va = RB_ROOT;
@@ -1249,7 +1242,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        INIT_LIST_HEAD(&vm->invalidated);
        INIT_LIST_HEAD(&vm->cleared);
        INIT_LIST_HEAD(&vm->freed);
-
+       spin_lock_init(&vm->it_lock);
        pd_size = amdgpu_vm_directory_size(adev);
        pd_entries = amdgpu_vm_num_pdes(adev);
 
@@ -1269,8 +1262,14 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
                             NULL, NULL, &vm->page_directory);
        if (r)
                return r;
-
+       r = amdgpu_bo_reserve(vm->page_directory, false);
+       if (r) {
+               amdgpu_bo_unref(&vm->page_directory);
+               vm->page_directory = NULL;
+               return r;
+       }
        r = amdgpu_vm_clear_bo(adev, vm->page_directory);
+       amdgpu_bo_unreserve(vm->page_directory);
        if (r) {
                amdgpu_bo_unref(&vm->page_directory);
                vm->page_directory = NULL;
@@ -1313,11 +1312,28 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 
        amdgpu_bo_unref(&vm->page_directory);
        fence_put(vm->page_directory_fence);
-
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+               unsigned id = vm->ids[i].id;
+
+               atomic_long_cmpxchg(&adev->vm_manager.ids[id].owner,
+                                   (long)vm, 0);
                fence_put(vm->ids[i].flushed_updates);
-               fence_put(vm->ids[i].last_id_use);
        }
 
        mutex_destroy(&vm->mutex);
 }
+
+/**
+ * amdgpu_vm_manager_fini - cleanup VM manager
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Cleanup the VM manager and free resources.
+ */
+void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       for (i = 0; i < AMDGPU_NUM_VM; ++i)
+               fence_put(adev->vm_manager.ids[i].active);
+}
index a1a35a5df8e71357eea132019d3500a35a89fce4..57a2e347f04dc33a0f34394895900bf2d0552aa5 100644 (file)
@@ -6569,12 +6569,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
                switch (state) {
                case AMDGPU_IRQ_STATE_DISABLE:
                        cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
                        WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
                        break;
                case AMDGPU_IRQ_STATE_ENABLE:
                        cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
+                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
                        WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
                        break;
                default:
@@ -6586,12 +6586,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
                switch (state) {
                case AMDGPU_IRQ_STATE_DISABLE:
                        cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
                        WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
                        break;
                case AMDGPU_IRQ_STATE_ENABLE:
                        cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
-                       cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
+                       cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
                        WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
                        break;
                default:
index 6776cf756d403415e29fc836785c66b828106879..e1dcab98e24944217d1e6a7485e5bee42587c0b8 100644 (file)
@@ -268,7 +268,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
        mmCGTT_CP_CLK_CTRL, 0xffffffff, 0x00000100,
        mmCGTT_CPC_CLK_CTRL, 0xffffffff, 0x00000100,
        mmCGTT_CPF_CLK_CTRL, 0xffffffff, 0x40000100,
-       mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00600100,
        mmCGTT_GDS_CLK_CTRL, 0xffffffff, 0x00000100,
        mmCGTT_IA_CLK_CTRL, 0xffffffff, 0x06000100,
        mmCGTT_PA_CLK_CTRL, 0xffffffff, 0x00000100,
@@ -296,10 +295,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
        mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96e00200,
        mmCP_RB_WPTR_POLL_CNTL, 0xffffffff, 0x00900100,
        mmRLC_CGCG_CGLS_CTRL, 0xffffffff, 0x0020003c,
-       mmPCIE_INDEX, 0xffffffff, 0x0140001c,
-       mmPCIE_DATA, 0x000f0000, 0x00000000,
-       mmCGTT_DRM_CLK_CTRL0, 0xff000fff, 0x00000100,
-       mmHDP_XDP_CGTT_BLK_CTRL, 0xc0000fff, 0x00000104,
        mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
 };
 
@@ -1000,7 +995,7 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
                adev->gfx.config.max_cu_per_sh = 16;
                adev->gfx.config.max_sh_per_se = 1;
                adev->gfx.config.max_backends_per_se = 4;
-               adev->gfx.config.max_texture_channel_caches = 8;
+               adev->gfx.config.max_texture_channel_caches = 16;
                adev->gfx.config.max_gprs = 256;
                adev->gfx.config.max_gs_threads = 32;
                adev->gfx.config.max_hw_contexts = 8;
@@ -1613,6 +1608,296 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
                        WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
                }
        case CHIP_FIJI:
+               for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+                       switch (reg_offset) {
+                       case 0:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 1:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 2:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 3:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 4:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 5:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 6:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 7:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                               TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+                               break;
+                       case 8:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
+                               break;
+                       case 9:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 10:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 11:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       case 12:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       case 13:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 14:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 15:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 16:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       case 17:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       case 18:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 19:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 20:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 21:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 22:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 23:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 24:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 25:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 26:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+                               break;
+                       case 27:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 28:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+                               break;
+                       case 29:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       case 30:
+                               gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+                                               PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+                                               MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+                                               SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+                               break;
+                       default:
+                               gb_tile_moden = 0;
+                               break;
+                       }
+                       adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
+                       WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
+               }
+               for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
+                       switch (reg_offset) {
+                       case 0:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 1:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 2:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 3:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 4:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 5:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 6:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 8:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 9:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 10:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 11:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 12:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 13:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+                                               NUM_BANKS(ADDR_SURF_8_BANK));
+                               break;
+                       case 14:
+                               gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+                                               BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+                                               MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+                                               NUM_BANKS(ADDR_SURF_4_BANK));
+                               break;
+                       case 7:
+                               /* unused idx */
+                               continue;
+                       default:
+                               gb_tile_moden = 0;
+                               break;
+                       }
+                       adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
+                       WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
+               }
+               break;
        case CHIP_TONGA:
                for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
                        switch (reg_offset) {
@@ -2971,10 +3256,13 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
        amdgpu_ring_write(ring, mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
        switch (adev->asic_type) {
        case CHIP_TONGA:
-       case CHIP_FIJI:
                amdgpu_ring_write(ring, 0x16000012);
                amdgpu_ring_write(ring, 0x0000002A);
                break;
+       case CHIP_FIJI:
+               amdgpu_ring_write(ring, 0x3a00161a);
+               amdgpu_ring_write(ring, 0x0000002e);
+               break;
        case CHIP_TOPAZ:
        case CHIP_CARRIZO:
                amdgpu_ring_write(ring, 0x00000002);
index 85bbcdc73fff0198d350ac1468a8d552b3a450c7..7427d8cd4c43fae6068c8a3455ac98f3627ff044 100644 (file)
@@ -40,7 +40,7 @@
 static void gmc_v7_0_set_gart_funcs(struct amdgpu_device *adev);
 static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev);
 
-MODULE_FIRMWARE("radeon/boniare_mc.bin");
+MODULE_FIRMWARE("radeon/bonaire_mc.bin");
 MODULE_FIRMWARE("radeon/hawaii_mc.bin");
 
 /**
@@ -501,6 +501,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+       tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
        WREG32(mmVM_L2_CNTL, tmp);
        tmp = REG_SET_FIELD(0, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
@@ -960,12 +961,10 @@ static int gmc_v7_0_sw_init(void *handle)
 
 static int gmc_v7_0_sw_fini(void *handle)
 {
-       int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        if (adev->vm_manager.enabled) {
-               for (i = 0; i < AMDGPU_NUM_VM; ++i)
-                       fence_put(adev->vm_manager.active[i]);
+               amdgpu_vm_manager_fini(adev);
                gmc_v7_0_vm_fini(adev);
                adev->vm_manager.enabled = false;
        }
@@ -1010,12 +1009,10 @@ static int gmc_v7_0_hw_fini(void *handle)
 
 static int gmc_v7_0_suspend(void *handle)
 {
-       int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        if (adev->vm_manager.enabled) {
-               for (i = 0; i < AMDGPU_NUM_VM; ++i)
-                       fence_put(adev->vm_manager.active[i]);
+               amdgpu_vm_manager_fini(adev);
                gmc_v7_0_vm_fini(adev);
                adev->vm_manager.enabled = false;
        }
index 1bcc4e74e3b485d694d9b91417b76998868b0e6f..cb0e50ebb5285cef90b4a2879cd3cd800129c296 100644 (file)
@@ -629,6 +629,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
+       tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
        WREG32(mmVM_L2_CNTL, tmp);
        tmp = RREG32(mmVM_L2_CNTL2);
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
@@ -979,12 +980,10 @@ static int gmc_v8_0_sw_init(void *handle)
 
 static int gmc_v8_0_sw_fini(void *handle)
 {
-       int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        if (adev->vm_manager.enabled) {
-               for (i = 0; i < AMDGPU_NUM_VM; ++i)
-                       fence_put(adev->vm_manager.active[i]);
+               amdgpu_vm_manager_fini(adev);
                gmc_v8_0_vm_fini(adev);
                adev->vm_manager.enabled = false;
        }
@@ -1031,12 +1030,10 @@ static int gmc_v8_0_hw_fini(void *handle)
 
 static int gmc_v8_0_suspend(void *handle)
 {
-       int i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        if (adev->vm_manager.enabled) {
-               for (i = 0; i < AMDGPU_NUM_VM; ++i)
-                       fence_put(adev->vm_manager.active[i]);
+               amdgpu_vm_manager_fini(adev);
                gmc_v8_0_vm_fini(adev);
                adev->vm_manager.enabled = false;
        }
index 144f50acc9715c0e2b30b459e68fb7c9f7c543ba..c89dc777768f8cdabe3ce882483c134faa6aefa7 100644 (file)
@@ -16,6 +16,8 @@ TRACE_EVENT(amd_sched_job,
            TP_ARGS(sched_job),
            TP_STRUCT__entry(
                             __field(struct amd_sched_entity *, entity)
+                            __field(struct amd_sched_job *, sched_job)
+                            __field(struct fence *, fence)
                             __field(const char *, name)
                             __field(u32, job_count)
                             __field(int, hw_job_count)
@@ -23,16 +25,32 @@ TRACE_EVENT(amd_sched_job,
 
            TP_fast_assign(
                           __entry->entity = sched_job->s_entity;
+                          __entry->sched_job = sched_job;
+                          __entry->fence = &sched_job->s_fence->base;
                           __entry->name = sched_job->sched->name;
                           __entry->job_count = kfifo_len(
                                   &sched_job->s_entity->job_queue) / sizeof(sched_job);
                           __entry->hw_job_count = atomic_read(
                                   &sched_job->sched->hw_rq_count);
                           ),
-           TP_printk("entity=%p, ring=%s, job count:%u, hw job count:%d",
-                     __entry->entity, __entry->name, __entry->job_count,
-                     __entry->hw_job_count)
+           TP_printk("entity=%p, sched job=%p, fence=%p, ring=%s, job count:%u, hw job count:%d",
+                     __entry->entity, __entry->sched_job, __entry->fence, __entry->name,
+                     __entry->job_count, __entry->hw_job_count)
 );
+
+TRACE_EVENT(amd_sched_process_job,
+           TP_PROTO(struct amd_sched_fence *fence),
+           TP_ARGS(fence),
+           TP_STRUCT__entry(
+                   __field(struct fence *, fence)
+                   ),
+
+           TP_fast_assign(
+                   __entry->fence = &fence->base;
+                   ),
+           TP_printk("fence=%p signaled", __entry->fence)
+);
+
 #endif
 
 /* This part must be outside protection */
index 89619a5a4289b882bfbed1a8f3e84dcd6bb3b582..ea30d6ad4c137e60e6f9c1ce4265305d60f85cc9 100644 (file)
@@ -34,6 +34,9 @@ static struct amd_sched_job *
 amd_sched_entity_pop_job(struct amd_sched_entity *entity);
 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
 
+struct kmem_cache *sched_fence_slab;
+atomic_t sched_fence_slab_ref = ATOMIC_INIT(0);
+
 /* Initialize a given run queue struct */
 static void amd_sched_rq_init(struct amd_sched_rq *rq)
 {
@@ -273,22 +276,13 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
  *
  * Returns 0 for success, negative error code otherwise.
  */
-int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
+void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
 {
        struct amd_sched_entity *entity = sched_job->s_entity;
-       struct amd_sched_fence *fence = amd_sched_fence_create(
-               entity, sched_job->owner);
-
-       if (!fence)
-               return -ENOMEM;
-
-       fence_get(&fence->base);
-       sched_job->s_fence = fence;
 
        wait_event(entity->sched->job_scheduled,
                   amd_sched_entity_in(sched_job));
        trace_amd_sched_job(sched_job);
-       return 0;
 }
 
 /**
@@ -343,6 +337,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
                list_del_init(&s_fence->list);
                spin_unlock_irqrestore(&sched->fence_list_lock, flags);
        }
+       trace_amd_sched_process_job(s_fence);
        fence_put(&s_fence->base);
        wake_up_interruptible(&sched->wake_up_worker);
 }
@@ -450,6 +445,13 @@ int amd_sched_init(struct amd_gpu_scheduler *sched,
        init_waitqueue_head(&sched->wake_up_worker);
        init_waitqueue_head(&sched->job_scheduled);
        atomic_set(&sched->hw_rq_count, 0);
+       if (atomic_inc_return(&sched_fence_slab_ref) == 1) {
+               sched_fence_slab = kmem_cache_create(
+                       "amd_sched_fence", sizeof(struct amd_sched_fence), 0,
+                       SLAB_HWCACHE_ALIGN, NULL);
+               if (!sched_fence_slab)
+                       return -ENOMEM;
+       }
 
        /* Each scheduler will run on a seperate kernel thread */
        sched->thread = kthread_run(amd_sched_main, sched, sched->name);
@@ -470,4 +472,6 @@ void amd_sched_fini(struct amd_gpu_scheduler *sched)
 {
        if (sched->thread)
                kthread_stop(sched->thread);
+       if (atomic_dec_and_test(&sched_fence_slab_ref))
+               kmem_cache_destroy(sched_fence_slab);
 }
index 929e9aced04195e24ed5ddcae99ab385ce830898..939692b14f4b10ca3434f537f8ee2e214b2bec2e 100644 (file)
@@ -30,6 +30,9 @@
 struct amd_gpu_scheduler;
 struct amd_sched_rq;
 
+extern struct kmem_cache *sched_fence_slab;
+extern atomic_t sched_fence_slab_ref;
+
 /**
  * A scheduler entity is a wrapper around a job queue or a group
  * of other entities. Entities take turns emitting jobs from their 
@@ -76,7 +79,6 @@ struct amd_sched_job {
        struct amd_gpu_scheduler        *sched;
        struct amd_sched_entity         *s_entity;
        struct amd_sched_fence          *s_fence;
-       void                            *owner;
 };
 
 extern const struct fence_ops amd_sched_fence_ops;
@@ -128,7 +130,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
                          uint32_t jobs);
 void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
                           struct amd_sched_entity *entity);
-int amd_sched_entity_push_job(struct amd_sched_job *sched_job);
+void amd_sched_entity_push_job(struct amd_sched_job *sched_job);
 
 struct amd_sched_fence *amd_sched_fence_create(
        struct amd_sched_entity *s_entity, void *owner);
index d802638094f4bb3817bb6612f1e37bf2479cf142..8d2130b9ff05c4cea8823a8461f9e63bcb80c390 100644 (file)
@@ -32,7 +32,7 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *s_entity
        struct amd_sched_fence *fence = NULL;
        unsigned seq;
 
-       fence = kzalloc(sizeof(struct amd_sched_fence), GFP_KERNEL);
+       fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
        if (fence == NULL)
                return NULL;
        fence->owner = owner;
@@ -71,11 +71,17 @@ static bool amd_sched_fence_enable_signaling(struct fence *f)
        return true;
 }
 
+static void amd_sched_fence_release(struct fence *f)
+{
+       struct amd_sched_fence *fence = to_amd_sched_fence(f);
+       kmem_cache_free(sched_fence_slab, fence);
+}
+
 const struct fence_ops amd_sched_fence_ops = {
        .get_driver_name = amd_sched_fence_get_driver_name,
        .get_timeline_name = amd_sched_fence_get_timeline_name,
        .enable_signaling = amd_sched_fence_enable_signaling,
        .signaled = NULL,
        .wait = fence_default_wait,
-       .release = NULL,
+       .release = amd_sched_fence_release,
 };
index 7bb3845d997492d5aa60092e7441f445d74e6104..aeee083c7f95064fed6c6b08cd67b58d174204af 100644 (file)
@@ -1432,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state,
        return ret;
 }
 
+/**
+ * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
+ *
+ * @dev: drm device to check.
+ * @plane_mask: plane mask for planes that were updated.
+ * @ret: return value, can be -EDEADLK for a retry.
+ *
+ * Before doing an update plane->old_fb is set to plane->fb,
+ * but before dropping the locks old_fb needs to be set to NULL
+ * and plane->fb updated. This is a common operation for each
+ * atomic update, so this call is split off as a helper.
+ */
+void drm_atomic_clean_old_fb(struct drm_device *dev,
+                            unsigned plane_mask,
+                            int ret)
+{
+       struct drm_plane *plane;
+
+       /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
+        * locks (ie. while it is still safe to deref plane->state).  We
+        * need to do this here because the driver entry points cannot
+        * distinguish between legacy and atomic ioctls.
+        */
+       drm_for_each_plane_mask(plane, dev, plane_mask) {
+               if (ret == 0) {
+                       struct drm_framebuffer *new_fb = plane->state->fb;
+                       if (new_fb)
+                               drm_framebuffer_reference(new_fb);
+                       plane->fb = new_fb;
+                       plane->crtc = plane->state->crtc;
+
+                       if (plane->old_fb)
+                               drm_framebuffer_unreference(plane->old_fb);
+               }
+               plane->old_fb = NULL;
+       }
+}
+EXPORT_SYMBOL(drm_atomic_clean_old_fb);
+
 int drm_mode_atomic_ioctl(struct drm_device *dev,
                          void *data, struct drm_file *file_priv)
 {
@@ -1446,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        struct drm_plane *plane;
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
-       unsigned plane_mask = 0;
+       unsigned plane_mask;
        int ret = 0;
        unsigned int i, j;
 
@@ -1486,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
 
 retry:
+       plane_mask = 0;
        copied_objs = 0;
        copied_props = 0;
 
@@ -1576,24 +1616,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
        }
 
 out:
-       /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
-        * locks (ie. while it is still safe to deref plane->state).  We
-        * need to do this here because the driver entry points cannot
-        * distinguish between legacy and atomic ioctls.
-        */
-       drm_for_each_plane_mask(plane, dev, plane_mask) {
-               if (ret == 0) {
-                       struct drm_framebuffer *new_fb = plane->state->fb;
-                       if (new_fb)
-                               drm_framebuffer_reference(new_fb);
-                       plane->fb = new_fb;
-                       plane->crtc = plane->state->crtc;
-
-                       if (plane->old_fb)
-                               drm_framebuffer_unreference(plane->old_fb);
-               }
-               plane->old_fb = NULL;
-       }
+       drm_atomic_clean_old_fb(dev, plane_mask, ret);
 
        if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
                /*
index 0c6f62168776ee378ff0906d2269cd10221fb535..e5aec45bf9855bfb18192e46b5a9dfd05eb0d170 100644 (file)
@@ -210,6 +210,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
                return -EINVAL;
        }
 
+       if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
+               DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
+                                new_encoder->base.id,
+                                new_encoder->name,
+                                connector_state->crtc->base.id);
+               return -EINVAL;
+       }
+
        if (new_encoder == connector_state->best_encoder) {
                DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
                                 connector->base.id,
@@ -1553,6 +1561,9 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
                goto fail;
        }
 
+       if (plane_state->crtc && (plane == plane->crtc->cursor))
+               plane_state->state->legacy_cursor_update = true;
+
        ret = __drm_atomic_helper_disable_plane(plane, plane_state);
        if (ret != 0)
                goto fail;
@@ -1605,9 +1616,6 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
        plane_state->src_h = 0;
        plane_state->src_w = 0;
 
-       if (plane->crtc && (plane == plane->crtc->cursor))
-               plane_state->state->legacy_cursor_update = true;
-
        return 0;
 }
 
@@ -1741,6 +1749,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
        struct drm_crtc_state *crtc_state;
        struct drm_plane_state *primary_state;
        struct drm_crtc *crtc = set->crtc;
+       int hdisplay, vdisplay;
        int ret;
 
        crtc_state = drm_atomic_get_crtc_state(state, crtc);
@@ -1783,19 +1792,21 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
        if (ret != 0)
                return ret;
 
+       drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
+
        drm_atomic_set_fb_for_plane(primary_state, set->fb);
        primary_state->crtc_x = 0;
        primary_state->crtc_y = 0;
-       primary_state->crtc_h = set->mode->vdisplay;
-       primary_state->crtc_w = set->mode->hdisplay;
+       primary_state->crtc_h = vdisplay;
+       primary_state->crtc_w = hdisplay;
        primary_state->src_x = set->x << 16;
        primary_state->src_y = set->y << 16;
        if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
-               primary_state->src_h = set->mode->hdisplay << 16;
-               primary_state->src_w = set->mode->vdisplay << 16;
+               primary_state->src_h = hdisplay << 16;
+               primary_state->src_w = vdisplay << 16;
        } else {
-               primary_state->src_h = set->mode->vdisplay << 16;
-               primary_state->src_w = set->mode->hdisplay << 16;
+               primary_state->src_h = vdisplay << 16;
+               primary_state->src_w = hdisplay << 16;
        }
 
 commit:
index e673c13c7391153d6c7f3c54b7c56a0e17d26bca..69cbab5e5c81f29008247776d81447f21aede835 100644 (file)
@@ -342,6 +342,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
        struct drm_plane *plane;
        struct drm_atomic_state *state;
        int i, ret;
+       unsigned plane_mask;
 
        state = drm_atomic_state_alloc(dev);
        if (!state)
@@ -349,11 +350,10 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
 
        state->acquire_ctx = dev->mode_config.acquire_ctx;
 retry:
+       plane_mask = 0;
        drm_for_each_plane(plane, dev) {
                struct drm_plane_state *plane_state;
 
-               plane->old_fb = plane->fb;
-
                plane_state = drm_atomic_get_plane_state(state, plane);
                if (IS_ERR(plane_state)) {
                        ret = PTR_ERR(plane_state);
@@ -362,6 +362,9 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
 
                plane_state->rotation = BIT(DRM_ROTATE_0);
 
+               plane->old_fb = plane->fb;
+               plane_mask |= 1 << drm_plane_index(plane);
+
                /* disable non-primary: */
                if (plane->type == DRM_PLANE_TYPE_PRIMARY)
                        continue;
@@ -382,19 +385,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
        ret = drm_atomic_commit(state);
 
 fail:
-       drm_for_each_plane(plane, dev) {
-               if (ret == 0) {
-                       struct drm_framebuffer *new_fb = plane->state->fb;
-                       if (new_fb)
-                               drm_framebuffer_reference(new_fb);
-                       plane->fb = new_fb;
-                       plane->crtc = plane->state->crtc;
-
-                       if (plane->old_fb)
-                               drm_framebuffer_unreference(plane->old_fb);
-               }
-               plane->old_fb = NULL;
-       }
+       drm_atomic_clean_old_fb(dev, plane_mask, ret);
 
        if (ret == -EDEADLK)
                goto backoff;
@@ -1236,7 +1227,9 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_device *dev = fb_helper->dev;
        struct drm_atomic_state *state;
+       struct drm_plane *plane;
        int i, ret;
+       unsigned plane_mask;
 
        state = drm_atomic_state_alloc(dev);
        if (!state)
@@ -1244,19 +1237,22 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
 
        state->acquire_ctx = dev->mode_config.acquire_ctx;
 retry:
+       plane_mask = 0;
        for(i = 0; i < fb_helper->crtc_count; i++) {
                struct drm_mode_set *mode_set;
 
                mode_set = &fb_helper->crtc_info[i].mode_set;
 
-               mode_set->crtc->primary->old_fb = mode_set->crtc->primary->fb;
-
                mode_set->x = var->xoffset;
                mode_set->y = var->yoffset;
 
                ret = __drm_atomic_helper_set_config(mode_set, state);
                if (ret != 0)
                        goto fail;
+
+               plane = mode_set->crtc->primary;
+               plane_mask |= drm_plane_index(plane);
+               plane->old_fb = plane->fb;
        }
 
        ret = drm_atomic_commit(state);
@@ -1268,26 +1264,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
 
 
 fail:
-       for(i = 0; i < fb_helper->crtc_count; i++) {
-               struct drm_mode_set *mode_set;
-               struct drm_plane *plane;
-
-               mode_set = &fb_helper->crtc_info[i].mode_set;
-               plane = mode_set->crtc->primary;
-
-               if (ret == 0) {
-                       struct drm_framebuffer *new_fb = plane->state->fb;
-
-                       if (new_fb)
-                               drm_framebuffer_reference(new_fb);
-                       plane->fb = new_fb;
-                       plane->crtc = plane->state->crtc;
-
-                       if (plane->old_fb)
-                               drm_framebuffer_unreference(plane->old_fb);
-               }
-               plane->old_fb = NULL;
-       }
+       drm_atomic_clean_old_fb(dev, plane_mask, ret);
 
        if (ret == -EDEADLK)
                goto backoff;
index eba6337f5860cddf62efbe9fc6829db0c55343f6..2151ea551d3bd6526d850754b79ece388a9279df 100644 (file)
@@ -616,10 +616,18 @@ int drm_control(struct drm_device *dev, void *data,
 void drm_calc_timestamping_constants(struct drm_crtc *crtc,
                                     const struct drm_display_mode *mode)
 {
-       struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
+       struct drm_device *dev = crtc->dev;
+       unsigned int pipe = drm_crtc_index(crtc);
+       struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
        int linedur_ns = 0, framedur_ns = 0;
        int dotclock = mode->crtc_clock;
 
+       if (!dev->num_crtcs)
+               return;
+
+       if (WARN_ON(pipe >= dev->num_crtcs))
+               return;
+
        /* Valid dotclock? */
        if (dotclock > 0) {
                int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
index 8afda459a26e290fa218450c074089356ce31efb..95bb27de774f8fb2c5bb8cc83567a45eb83a8e43 100644 (file)
@@ -351,6 +351,8 @@ enum intel_dpll_id {
        /* hsw/bdw */
        DPLL_ID_WRPLL1 = 0,
        DPLL_ID_WRPLL2 = 1,
+       DPLL_ID_SPLL = 2,
+
        /* skl */
        DPLL_ID_SKL_DPLL1 = 0,
        DPLL_ID_SKL_DPLL2 = 1,
@@ -367,6 +369,7 @@ struct intel_dpll_hw_state {
 
        /* hsw, bdw */
        uint32_t wrpll;
+       uint32_t spll;
 
        /* skl */
        /*
@@ -2648,6 +2651,7 @@ struct i915_params {
        int enable_cmd_parser;
        /* leave bools at the end to not create holes */
        bool enable_hangcheck;
+       bool fastboot;
        bool prefault_disable;
        bool load_detect_test;
        bool reset;
index 5cf4a1998273c3cfcc494c83210c0bc572f35c2e..91bb1fc27420f5a58f9fc2ca962a4b452f9cb7e6 100644 (file)
@@ -3809,6 +3809,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
 int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_caching *args = data;
        struct drm_i915_gem_object *obj;
        enum i915_cache_level level;
@@ -3837,9 +3838,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
+       intel_runtime_pm_get(dev_priv);
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
-               return ret;
+               goto rpm_put;
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
        if (&obj->base == NULL) {
@@ -3852,6 +3855,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
        drm_gem_object_unreference(&obj->base);
 unlock:
        mutex_unlock(&dev->struct_mutex);
+rpm_put:
+       intel_runtime_pm_put(dev_priv);
+
        return ret;
 }
 
index 96bb23865eac7a6acf3a731c0c5ecc8bbd25a4e5..4be13a5eb932797b233911c1935d1233dc9354c7 100644 (file)
@@ -40,6 +40,7 @@ struct i915_params i915 __read_mostly = {
        .preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
        .disable_power_well = -1,
        .enable_ips = 1,
+       .fastboot = 0,
        .prefault_disable = 0,
        .load_detect_test = 0,
        .reset = true,
@@ -133,6 +134,10 @@ MODULE_PARM_DESC(disable_power_well,
 module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600);
 MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
 
+module_param_named(fastboot, i915.fastboot, bool, 0600);
+MODULE_PARM_DESC(fastboot,
+       "Try to skip unnecessary mode sets at boot time (default: false)");
+
 module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600);
 MODULE_PARM_DESC(prefault_disable,
        "Disable page prefaulting for pread/pwrite/reloc (default:false). "
index b84aaa0bb48a228aa297756c85b132c9790f0eb6..6a2c76e367a5dc327e45691e4ff0ddf6294471ea 100644 (file)
@@ -138,18 +138,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
        pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
 }
 
-static void hsw_crt_pre_enable(struct intel_encoder *encoder)
-{
-       struct drm_device *dev = encoder->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
-       I915_WRITE(SPLL_CTL,
-                  SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
-       POSTING_READ(SPLL_CTL);
-       udelay(20);
-}
-
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -216,19 +204,6 @@ static void pch_post_disable_crt(struct intel_encoder *encoder)
        intel_disable_crt(encoder);
 }
 
-static void hsw_crt_post_disable(struct intel_encoder *encoder)
-{
-       struct drm_device *dev = encoder->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t val;
-
-       DRM_DEBUG_KMS("Disabling SPLL\n");
-       val = I915_READ(SPLL_CTL);
-       WARN_ON(!(val & SPLL_PLL_ENABLE));
-       I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
-       POSTING_READ(SPLL_CTL);
-}
-
 static void intel_enable_crt(struct intel_encoder *encoder)
 {
        struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -280,6 +255,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
        if (HAS_DDI(dev)) {
                pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
                pipe_config->port_clock = 135000 * 2;
+
+               pipe_config->dpll_hw_state.wrpll = 0;
+               pipe_config->dpll_hw_state.spll =
+                       SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
        }
 
        return true;
@@ -860,8 +839,6 @@ void intel_crt_init(struct drm_device *dev)
        if (HAS_DDI(dev)) {
                crt->base.get_config = hsw_crt_get_config;
                crt->base.get_hw_state = intel_ddi_get_hw_state;
-               crt->base.pre_enable = hsw_crt_pre_enable;
-               crt->base.post_disable = hsw_crt_post_disable;
        } else {
                crt->base.get_config = intel_crt_get_config;
                crt->base.get_hw_state = intel_crt_get_hw_state;
index b25e99a432fbd3af325770b0a669d27ede78952b..a6752a61d99f268217e7054a8531036d109be7ee 100644 (file)
@@ -1286,6 +1286,18 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
                }
 
                crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
+       } else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
+               struct drm_atomic_state *state = crtc_state->base.state;
+               struct intel_shared_dpll_config *spll =
+                       &intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
+
+               if (spll->crtc_mask &&
+                   WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
+                       return false;
+
+               crtc_state->shared_dpll = DPLL_ID_SPLL;
+               spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
+               spll->crtc_mask |= 1 << intel_crtc->pipe;
        }
 
        return true;
@@ -2437,7 +2449,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
        }
 }
 
-static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
                               struct intel_shared_dpll *pll)
 {
        I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
@@ -2445,8 +2457,16 @@ static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
        udelay(20);
 }
 
-static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
+static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
                                struct intel_shared_dpll *pll)
+{
+       I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
+       POSTING_READ(SPLL_CTL);
+       udelay(20);
+}
+
+static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
+                                 struct intel_shared_dpll *pll)
 {
        uint32_t val;
 
@@ -2455,9 +2475,19 @@ static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
        POSTING_READ(WRPLL_CTL(pll->id));
 }
 
-static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
-                                    struct intel_shared_dpll *pll,
-                                    struct intel_dpll_hw_state *hw_state)
+static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll)
+{
+       uint32_t val;
+
+       val = I915_READ(SPLL_CTL);
+       I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+       POSTING_READ(SPLL_CTL);
+}
+
+static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
+                                      struct intel_shared_dpll *pll,
+                                      struct intel_dpll_hw_state *hw_state)
 {
        uint32_t val;
 
@@ -2470,25 +2500,50 @@ static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        return val & WRPLL_PLL_ENABLE;
 }
 
+static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
+                                     struct intel_shared_dpll *pll,
+                                     struct intel_dpll_hw_state *hw_state)
+{
+       uint32_t val;
+
+       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       val = I915_READ(SPLL_CTL);
+       hw_state->spll = val;
+
+       return val & SPLL_PLL_ENABLE;
+}
+
+
 static const char * const hsw_ddi_pll_names[] = {
        "WRPLL 1",
        "WRPLL 2",
+       "SPLL"
 };
 
 static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
 {
        int i;
 
-       dev_priv->num_shared_dpll = 2;
+       dev_priv->num_shared_dpll = 3;
 
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+       for (i = 0; i < 2; i++) {
                dev_priv->shared_dplls[i].id = i;
                dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
-               dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
-               dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
+               dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
+               dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
                dev_priv->shared_dplls[i].get_hw_state =
-                       hsw_ddi_pll_get_hw_state;
+                       hsw_ddi_wrpll_get_hw_state;
        }
+
+       /* SPLL is special, but needs to be initialized anyway.. */
+       dev_priv->shared_dplls[i].id = i;
+       dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
+       dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
+       dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
+       dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
+
 }
 
 static const char * const skl_ddi_pll_names[] = {
index f62ffc04c21d516d193dbaadf1cbaa28ca2d0b94..71860f8680f9fb95efae6ea310be6ef450d25e57 100644 (file)
@@ -2646,11 +2646,13 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
-       plane_state->src_x = plane_state->src_y = 0;
+       plane_state->src_x = 0;
+       plane_state->src_y = 0;
        plane_state->src_w = fb->width << 16;
        plane_state->src_h = fb->height << 16;
 
-       plane_state->crtc_x = plane_state->src_y = 0;
+       plane_state->crtc_x = 0;
+       plane_state->crtc_y = 0;
        plane_state->crtc_w = fb->width;
        plane_state->crtc_h = fb->height;
 
@@ -4237,6 +4239,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
        struct intel_shared_dpll *pll;
        struct intel_shared_dpll_config *shared_dpll;
        enum intel_dpll_id i;
+       int max = dev_priv->num_shared_dpll;
 
        shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
 
@@ -4271,9 +4274,11 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
                WARN_ON(shared_dpll[i].crtc_mask);
 
                goto found;
-       }
+       } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
+               /* Do not consider SPLL */
+               max = 2;
 
-       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+       for (i = 0; i < max; i++) {
                pll = &dev_priv->shared_dplls[i];
 
                /* Only want to check enabled timings first */
@@ -9723,6 +9728,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
        case PORT_CLK_SEL_WRPLL2:
                pipe_config->shared_dpll = DPLL_ID_WRPLL2;
                break;
+       case PORT_CLK_SEL_SPLL:
+               pipe_config->shared_dpll = DPLL_ID_SPLL;
        }
 }
 
@@ -12003,9 +12010,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                              pipe_config->dpll_hw_state.cfgcr1,
                              pipe_config->dpll_hw_state.cfgcr2);
        } else if (HAS_DDI(dev)) {
-               DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x\n",
+               DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
                              pipe_config->ddi_pll_sel,
-                             pipe_config->dpll_hw_state.wrpll);
+                             pipe_config->dpll_hw_state.wrpll,
+                             pipe_config->dpll_hw_state.spll);
        } else {
                DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
                              "fp0: 0x%x, fp1: 0x%x\n",
@@ -12528,6 +12536,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
        PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
        PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
+       PIPE_CONF_CHECK_X(dpll_hw_state.spll);
        PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
        PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
        PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
@@ -13032,6 +13041,9 @@ static int intel_atomic_check(struct drm_device *dev,
                struct intel_crtc_state *pipe_config =
                        to_intel_crtc_state(crtc_state);
 
+               memset(&to_intel_crtc(crtc)->atomic, 0,
+                      sizeof(struct intel_crtc_atomic_commit));
+
                /* Catch I915_MODE_FLAG_INHERITED */
                if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
                        crtc_state->mode_changed = true;
@@ -13056,7 +13068,8 @@ static int intel_atomic_check(struct drm_device *dev,
                if (ret)
                        return ret;
 
-               if (intel_pipe_config_compare(state->dev,
+               if (i915.fastboot &&
+                   intel_pipe_config_compare(state->dev,
                                        to_intel_crtc_state(crtc->state),
                                        pipe_config, true)) {
                        crtc_state->mode_changed = false;
@@ -14364,16 +14377,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 intel_user_framebuffer_create(struct drm_device *dev,
                              struct drm_file *filp,
-                             struct drm_mode_fb_cmd2 *mode_cmd)
+                             struct drm_mode_fb_cmd2 *user_mode_cmd)
 {
        struct drm_i915_gem_object *obj;
+       struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
-                                               mode_cmd->handles[0]));
+                                               mode_cmd.handles[0]));
        if (&obj->base == NULL)
                return ERR_PTR(-ENOENT);
 
-       return intel_framebuffer_create(dev, mode_cmd, obj);
+       return intel_framebuffer_create(dev, &mode_cmd, obj);
 }
 
 #ifndef CONFIG_DRM_FBDEV_EMULATION
@@ -14705,6 +14719,9 @@ static struct intel_quirk intel_quirks[] = {
        /* Apple Macbook 2,1 (Core 2 T7400) */
        { 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
 
+       /* Apple Macbook 4,1 */
+       { 0x2a02, 0x106b, 0x00a1, quirk_backlight_present },
+
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
index d52a15df6917cc054df25cccdba43f6ef8abfaa0..071a76b9ac523355e296836f81969374caaa6d86 100644 (file)
@@ -4449,7 +4449,7 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
        POSTING_READ(GEN6_RPNSWREQ);
 
        dev_priv->rps.cur_freq = val;
-       trace_intel_gpu_freq_change(val * 50);
+       trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val));
 }
 
 static void valleyview_set_rps(struct drm_device *dev, u8 val)
@@ -7255,7 +7255,8 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
        if (IS_GEN9(dev_priv->dev))
-               return (val * GT_FREQUENCY_MULTIPLIER) / GEN9_FREQ_SCALER;
+               return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
+                                        GEN9_FREQ_SCALER);
        else if (IS_CHERRYVIEW(dev_priv->dev))
                return chv_gpu_freq(dev_priv, val);
        else if (IS_VALLEYVIEW(dev_priv->dev))
@@ -7267,13 +7268,14 @@ int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
 int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
        if (IS_GEN9(dev_priv->dev))
-               return (val * GEN9_FREQ_SCALER) / GT_FREQUENCY_MULTIPLIER;
+               return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
+                                        GT_FREQUENCY_MULTIPLIER);
        else if (IS_CHERRYVIEW(dev_priv->dev))
                return chv_freq_opcode(dev_priv, val);
        else if (IS_VALLEYVIEW(dev_priv->dev))
                return byt_freq_opcode(dev_priv, val);
        else
-               return val / GT_FREQUENCY_MULTIPLIER;
+               return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
 }
 
 struct request_boost {
index 4f2068fe5d885cdba438a44745c27ccade5df9d0..a7bf6a90eae5a30e40ae3c1c5dbada0ea893bc8b 100644 (file)
@@ -70,6 +70,11 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
        BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
        BUG_ON(pixels_current == pixels_prev);
 
+       if (!handle || !file_priv) {
+               mga_hide_cursor(mdev);
+               return 0;
+       }
+
        obj = drm_gem_object_lookup(dev, file_priv, handle);
        if (!obj)
                return -ENOENT;
@@ -88,12 +93,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
                goto out_unreserve1;
        }
 
-       if (!handle) {
-               mga_hide_cursor(mdev);
-               ret = 0;
-               goto out1;
-       }
-
        /* Move cursor buffers into VRAM if they aren't already */
        if (!pixels_1->pin_count) {
                ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,
index d3024883b8449db854dbb93d0393ef1728ff0748..84d45633d28c9b1c58f58dc6ec6383eba2207230 100644 (file)
@@ -221,11 +221,17 @@ int radeon_bo_create(struct radeon_device *rdev,
        if (!(rdev->flags & RADEON_IS_PCIE))
                bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
 
+       /* Write-combined CPU mappings of GTT cause GPU hangs with RV6xx
+        * See https://bugs.freedesktop.org/show_bug.cgi?id=91268
+        */
+       if (rdev->family >= CHIP_RV610 && rdev->family <= CHIP_RV635)
+               bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
+
 #ifdef CONFIG_X86_32
        /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
         * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
         */
-       bo->flags &= ~RADEON_GEM_GTT_WC;
+       bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
 #elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
        /* Don't try to enable write-combining when it can't work, or things
         * may be slow
@@ -235,9 +241,10 @@ int radeon_bo_create(struct radeon_device *rdev,
 #warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
         thanks to write-combining
 
-       DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
-                     "better performance thanks to write-combining\n");
-       bo->flags &= ~RADEON_GEM_GTT_WC;
+       if (bo->flags & RADEON_GEM_GTT_WC)
+               DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
+                             "better performance thanks to write-combining\n");
+       bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
 #endif
 
        radeon_ttm_placement_from_domain(bo, domain);
index 6d80dde23400003dd1362539929c1d402a6500e3..f4f03dcc153049358b7167695c27fff60af55d46 100644 (file)
@@ -1542,8 +1542,7 @@ int radeon_pm_late_init(struct radeon_device *rdev)
                                ret = device_create_file(rdev->dev, &dev_attr_power_method);
                                if (ret)
                                        DRM_ERROR("failed to create device file for power method\n");
-                               if (!ret)
-                                       rdev->pm.sysfs_initialized = true;
+                               rdev->pm.sysfs_initialized = true;
                        }
 
                        mutex_lock(&rdev->pm.mutex);
index e72bf46042e0a42f469cbfd8ff285b1ae9abb155..a82b891ae1febb4a4523fbde3dea3de398c8a40c 100644 (file)
@@ -2927,7 +2927,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
        { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
        { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
        { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
-       { PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
        { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
        { 0, 0, 0, 0 },
 };
index d26e0cc7dc4ba9fd699861cb6af1dbe882629c4d..f22e1e1ee64aae52a1e3efb657a78790bd6ba573 100644 (file)
@@ -19,7 +19,6 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_of.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
@@ -419,6 +418,29 @@ static int compare_of(struct device *dev, void *data)
        return dev->of_node == np;
 }
 
+static void rockchip_add_endpoints(struct device *dev,
+                                  struct component_match **match,
+                                  struct device_node *port)
+{
+       struct device_node *ep, *remote;
+
+       for_each_child_of_node(port, ep) {
+               remote = of_graph_get_remote_port_parent(ep);
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
+                       continue;
+               } else if (!of_device_is_available(remote->parent)) {
+                       dev_warn(dev, "parent device of %s is not available\n",
+                                remote->full_name);
+                       of_node_put(remote);
+                       continue;
+               }
+
+               component_match_add(dev, match, compare_of, remote);
+               of_node_put(remote);
+       }
+}
+
 static int rockchip_drm_bind(struct device *dev)
 {
        struct drm_device *drm;
@@ -461,14 +483,61 @@ static const struct component_master_ops rockchip_drm_ops = {
 
 static int rockchip_drm_platform_probe(struct platform_device *pdev)
 {
-       int ret = drm_of_component_probe(&pdev->dev, compare_of,
-                                        &rockchip_drm_ops);
+       struct device *dev = &pdev->dev;
+       struct component_match *match = NULL;
+       struct device_node *np = dev->of_node;
+       struct device_node *port;
+       int i;
 
-       /* keep compatibility with old code that was returning -ENODEV */
-       if (ret == -EINVAL)
+       if (!np)
                return -ENODEV;
+       /*
+        * Bind the crtc ports first, so that
+        * drm_of_find_possible_crtcs called from encoder .bind callbacks
+        * works as expected.
+        */
+       for (i = 0;; i++) {
+               port = of_parse_phandle(np, "ports", i);
+               if (!port)
+                       break;
+
+               if (!of_device_is_available(port->parent)) {
+                       of_node_put(port);
+                       continue;
+               }
 
-       return ret;
+               component_match_add(dev, &match, compare_of, port->parent);
+               of_node_put(port);
+       }
+
+       if (i == 0) {
+               dev_err(dev, "missing 'ports' property\n");
+               return -ENODEV;
+       }
+
+       if (!match) {
+               dev_err(dev, "No available vop found for display-subsystem.\n");
+               return -ENODEV;
+       }
+       /*
+        * For each bound crtc, bind the encoders attached to its
+        * remote endpoint.
+        */
+       for (i = 0;; i++) {
+               port = of_parse_phandle(np, "ports", i);
+               if (!port)
+                       break;
+
+               if (!of_device_is_available(port->parent)) {
+                       of_node_put(port);
+                       continue;
+               }
+
+               rockchip_add_endpoints(dev, &match, port);
+               of_node_put(port);
+       }
+
+       return component_master_add_with_match(dev, &rockchip_drm_ops, match);
 }
 
 static int rockchip_drm_platform_remove(struct platform_device *pdev)
index fbccc105819b707c2b3be9383dfd1898cee239af..10c1b1926e6f9665b083df291632924d91c12ef5 100644 (file)
@@ -6,12 +6,6 @@ config DRM_STI
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_CMA_HELPER
        select DRM_PANEL
-       select FW_LOADER_USER_HELPER_FALLBACK
+       select FW_LOADER
        help
          Choose this option to enable DRM on STM stiH41x chipset
-
-config DRM_STI_FBDEV
-       bool "DRM frame buffer device for STMicroelectronics SoC stiH41x Serie"
-       depends on DRM_STI
-       help
-         Choose this option to enable FBDEV on top of DRM for STM stiH41x chipset
index e27490b492a5280a254b9a196d452f429abb9466..b8057620b3b35702f23476584c15efc0d2a7763e 100644 (file)
@@ -1,26 +1,23 @@
-sticompositor-y := \
+sti-drm-y := \
        sti_mixer.o \
        sti_gdp.o \
        sti_vid.o \
        sti_cursor.o \
        sti_compositor.o \
        sti_crtc.o \
-       sti_plane.o
-
-stihdmi-y := sti_hdmi.o \
+       sti_plane.o \
+       sti_crtc.o \
+       sti_plane.o \
+       sti_hdmi.o \
        sti_hdmi_tx3g0c55phy.o \
        sti_hdmi_tx3g4c28phy.o \
-
-stidvo-y := sti_dvo.o \
-       sti_awg_utils.o
-
-obj-$(CONFIG_DRM_STI) = \
+       sti_dvo.o \
+       sti_awg_utils.o \
        sti_vtg.o \
        sti_vtac.o \
-       stihdmi.o \
        sti_hda.o \
        sti_tvout.o \
-       sticompositor.o \
        sti_hqvdp.o \
-       stidvo.o \
        sti_drv.o
+
+obj-$(CONFIG_DRM_STI) = sti-drm.o
index 6029a2e3db1dc8feb5243e992abef98594d2a766..00d0698be9d33e7b4517c9e39c186607676a8399 100644 (file)
@@ -65,7 +65,6 @@ static int awg_generate_instr(enum opcode opcode,
 
                        mux = 0;
                        data_enable = 0;
-                       arg = (arg << 22) >> 22;
                        arg &= (0x3ff);
                        break;
                case REPEAT:
@@ -77,14 +76,12 @@ static int awg_generate_instr(enum opcode opcode,
 
                        mux = 0;
                        data_enable = 0;
-                       arg = (arg << 22) >> 22;
                        arg &= (0x3ff);
                        break;
                case JUMP:
                        mux = 0;
                        data_enable = 0;
                        arg |= 0x40; /* for jump instruction 7th bit is 1 */
-                       arg = (arg << 22) >> 22;
                        arg &= 0x3ff;
                        break;
                case STOP:
@@ -94,7 +91,6 @@ static int awg_generate_instr(enum opcode opcode,
                case RPTSET:
                case RPLSET:
                case HOLD:
-                       arg = (arg << 24) >> 24;
                        arg &= (0x0ff);
                        break;
                default:
index c652627b1bcadbe05a1a759677724f7be8819c0a..afed2171beb9a4ce4e2a6031eb139fe0247b1ae0 100644 (file)
@@ -263,7 +263,7 @@ static int sti_compositor_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_driver sti_compositor_driver = {
+struct platform_driver sti_compositor_driver = {
        .driver = {
                .name = "sti-compositor",
                .of_match_table = compositor_of_match,
@@ -272,8 +272,6 @@ static struct platform_driver sti_compositor_driver = {
        .remove = sti_compositor_remove,
 };
 
-module_platform_driver(sti_compositor_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 493c4a3006adb4b62e7074aff5f68f80dc7463c3..3ae09dcd4fd86c65fad95b13fc60aa596a1271e4 100644 (file)
@@ -226,7 +226,7 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
        }
 }
 
-static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
+static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
        .enable = sti_crtc_enable,
        .disable = sti_crtc_disabling,
        .mode_fixup = sti_crtc_mode_fixup,
@@ -254,15 +254,17 @@ static int sti_crtc_set_property(struct drm_crtc *crtc,
 int sti_crtc_vblank_cb(struct notifier_block *nb,
                       unsigned long event, void *data)
 {
-       struct drm_device *drm_dev;
        struct sti_compositor *compo =
                container_of(nb, struct sti_compositor, vtg_vblank_nb);
-       int *crtc = data;
+       struct drm_crtc *crtc = data;
+       struct sti_mixer *mixer;
        unsigned long flags;
        struct sti_private *priv;
+       unsigned int pipe;
 
-       drm_dev = compo->mixer[*crtc]->drm_crtc.dev;
-       priv = drm_dev->dev_private;
+       priv = crtc->dev->dev_private;
+       pipe = drm_crtc_index(crtc);
+       mixer = compo->mixer[pipe];
 
        if ((event != VTG_TOP_FIELD_EVENT) &&
            (event != VTG_BOTTOM_FIELD_EVENT)) {
@@ -270,30 +272,30 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
                return -EINVAL;
        }
 
-       drm_handle_vblank(drm_dev, *crtc);
+       drm_crtc_handle_vblank(crtc);
 
-       spin_lock_irqsave(&drm_dev->event_lock, flags);
-       if (compo->mixer[*crtc]->pending_event) {
-               drm_send_vblank_event(drm_dev, -1,
-                                     compo->mixer[*crtc]->pending_event);
-               drm_vblank_put(drm_dev, *crtc);
-               compo->mixer[*crtc]->pending_event = NULL;
+       spin_lock_irqsave(&crtc->dev->event_lock, flags);
+       if (mixer->pending_event) {
+               drm_crtc_send_vblank_event(crtc, mixer->pending_event);
+               drm_crtc_vblank_put(crtc);
+               mixer->pending_event = NULL;
        }
-       spin_unlock_irqrestore(&drm_dev->event_lock, flags);
+       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
-       if (compo->mixer[*crtc]->status == STI_MIXER_DISABLING) {
+       if (mixer->status == STI_MIXER_DISABLING) {
                struct drm_plane *p;
 
                /* Disable mixer only if all overlay planes (GDP and VDP)
                 * are disabled */
-               list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
+               list_for_each_entry(p, &crtc->dev->mode_config.plane_list,
+                                   head) {
                        struct sti_plane *plane = to_sti_plane(p);
 
                        if ((plane->desc & STI_PLANE_TYPE_MASK) <= STI_VDP)
                                if (plane->status != STI_PLANE_DISABLED)
                                        return 0;
                }
-               sti_crtc_disable(&compo->mixer[*crtc]->drm_crtc);
+               sti_crtc_disable(crtc);
        }
 
        return 0;
@@ -304,25 +306,26 @@ int sti_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
        struct sti_private *dev_priv = dev->dev_private;
        struct sti_compositor *compo = dev_priv->compo;
        struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+       struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
 
        DRM_DEBUG_DRIVER("\n");
 
        if (sti_vtg_register_client(pipe == STI_MIXER_MAIN ?
                        compo->vtg_main : compo->vtg_aux,
-                       vtg_vblank_nb, pipe)) {
+                       vtg_vblank_nb, crtc)) {
                DRM_ERROR("Cannot register VTG notifier\n");
                return -EINVAL;
        }
 
        return 0;
 }
-EXPORT_SYMBOL(sti_crtc_enable_vblank);
 
 void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
 {
        struct sti_private *priv = drm_dev->dev_private;
        struct sti_compositor *compo = priv->compo;
        struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb;
+       struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
 
        DRM_DEBUG_DRIVER("\n");
 
@@ -332,13 +335,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
 
        /* free the resources of the pending requests */
        if (compo->mixer[pipe]->pending_event) {
-               drm_vblank_put(drm_dev, pipe);
+               drm_crtc_vblank_put(crtc);
                compo->mixer[pipe]->pending_event = NULL;
        }
 }
-EXPORT_SYMBOL(sti_crtc_disable_vblank);
 
-static struct drm_crtc_funcs sti_crtc_funcs = {
+static const struct drm_crtc_funcs sti_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
        .destroy = sti_crtc_destroy,
@@ -357,7 +359,6 @@ bool sti_crtc_is_main(struct drm_crtc *crtc)
 
        return false;
 }
-EXPORT_SYMBOL(sti_crtc_is_main);
 
 int sti_crtc_init(struct drm_device *drm_dev, struct sti_mixer *mixer,
                  struct drm_plane *primary, struct drm_plane *cursor)
index f8469967a0bfbb43dcf5faee539ac9b5d5b5f328..1469987949d88f8b43cfdd97990e925156a149ec 100644 (file)
@@ -107,7 +107,7 @@ static int sti_atomic_commit(struct drm_device *drm,
        return 0;
 }
 
-static struct drm_mode_config_funcs sti_mode_config_funcs = {
+static const struct drm_mode_config_funcs sti_mode_config_funcs = {
        .fb_create = drm_fb_cma_create,
        .atomic_check = drm_atomic_helper_check,
        .atomic_commit = sti_atomic_commit,
@@ -123,8 +123,8 @@ static void sti_mode_config_init(struct drm_device *dev)
         * this value would be used to check framebuffer size limitation
         * at drm_mode_addfb().
         */
-       dev->mode_config.max_width = STI_MAX_FB_HEIGHT;
-       dev->mode_config.max_height = STI_MAX_FB_WIDTH;
+       dev->mode_config.max_width = STI_MAX_FB_WIDTH;
+       dev->mode_config.max_height = STI_MAX_FB_HEIGHT;
 
        dev->mode_config.funcs = &sti_mode_config_funcs;
 }
@@ -160,11 +160,10 @@ static int sti_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_reset(dev);
 
-#ifdef CONFIG_DRM_STI_FBDEV
        drm_fbdev_cma_init(dev, 32,
                           dev->mode_config.num_crtc,
                           dev->mode_config.num_connector);
-#endif
+
        return 0;
 }
 
@@ -287,7 +286,29 @@ static struct platform_driver sti_platform_driver = {
        },
 };
 
-module_platform_driver(sti_platform_driver);
+static struct platform_driver * const drivers[] = {
+       &sti_tvout_driver,
+       &sti_vtac_driver,
+       &sti_hqvdp_driver,
+       &sti_hdmi_driver,
+       &sti_hda_driver,
+       &sti_dvo_driver,
+       &sti_vtg_driver,
+       &sti_compositor_driver,
+       &sti_platform_driver,
+};
+
+static int sti_drm_init(void)
+{
+       return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_init(sti_drm_init);
+
+static void sti_drm_exit(void)
+{
+       platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(sti_drm_exit);
 
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
index 9372f69e1859ff96986b0cea5c795f3d3325c047..30ddc20841c343a6b1c904864107e6b4a4d732a0 100644 (file)
@@ -32,4 +32,13 @@ struct sti_private {
        } commit;
 };
 
+extern struct platform_driver sti_tvout_driver;
+extern struct platform_driver sti_vtac_driver;
+extern struct platform_driver sti_hqvdp_driver;
+extern struct platform_driver sti_hdmi_driver;
+extern struct platform_driver sti_hda_driver;
+extern struct platform_driver sti_dvo_driver;
+extern struct platform_driver sti_vtg_driver;
+extern struct platform_driver sti_compositor_driver;
+
 #endif
index d141d645bd13acd47c99b9c6b1de839e442fc280..45cbe2bf7dd60da4dbe6b513e21f8a890509c894 100644 (file)
@@ -329,7 +329,8 @@ struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector)
        return dvo_connector->encoder;
 }
 
-static struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = {
        .get_modes = sti_dvo_connector_get_modes,
        .mode_valid = sti_dvo_connector_mode_valid,
        .best_encoder = sti_dvo_best_encoder,
@@ -364,7 +365,7 @@ static void sti_dvo_connector_destroy(struct drm_connector *connector)
        kfree(dvo_connector);
 }
 
-static struct drm_connector_funcs sti_dvo_connector_funcs = {
+static const struct drm_connector_funcs sti_dvo_connector_funcs = {
        .dpms = drm_atomic_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = sti_dvo_connector_detect,
@@ -557,8 +558,6 @@ struct platform_driver sti_dvo_driver = {
        .remove = sti_dvo_remove,
 };
 
-module_platform_driver(sti_dvo_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 9365670427ad26ef7224b085557c678769c63c6c..c85dc7d6b0053d2f45a673e43bbda6b99032bcf7 100644 (file)
@@ -492,7 +492,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
                /* Register gdp callback */
                if (sti_vtg_register_client(mixer->id == STI_MIXER_MAIN ?
                                compo->vtg_main : compo->vtg_aux,
-                               &gdp->vtg_field_nb, mixer->id)) {
+                               &gdp->vtg_field_nb, crtc)) {
                        DRM_ERROR("Cannot register VTG notifier\n");
                        return;
                }
index 598cd78b0b163cd2e86f92a68e5386325a3a357f..d735daccd4589b03528dd61eb350f9ded3b1da2d 100644 (file)
@@ -589,7 +589,8 @@ struct drm_encoder *sti_hda_best_encoder(struct drm_connector *connector)
        return hda_connector->encoder;
 }
 
-static struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_hda_connector_helper_funcs = {
        .get_modes = sti_hda_connector_get_modes,
        .mode_valid = sti_hda_connector_mode_valid,
        .best_encoder = sti_hda_best_encoder,
@@ -611,7 +612,7 @@ static void sti_hda_connector_destroy(struct drm_connector *connector)
        kfree(hda_connector);
 }
 
-static struct drm_connector_funcs sti_hda_connector_funcs = {
+static const struct drm_connector_funcs sti_hda_connector_funcs = {
        .dpms = drm_atomic_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = sti_hda_connector_detect,
@@ -784,8 +785,6 @@ struct platform_driver sti_hda_driver = {
        .remove = sti_hda_remove,
 };
 
-module_platform_driver(sti_hda_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 09e29e43423e21e6326b54e159ed81ffc4114b86..cd501563c0cc58f83b9992e7e83e09e048dfd32a 100644 (file)
@@ -628,7 +628,8 @@ struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
        return hdmi_connector->encoder;
 }
 
-static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
+static const
+struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
        .get_modes = sti_hdmi_connector_get_modes,
        .mode_valid = sti_hdmi_connector_mode_valid,
        .best_encoder = sti_hdmi_best_encoder,
@@ -663,7 +664,7 @@ static void sti_hdmi_connector_destroy(struct drm_connector *connector)
        kfree(hdmi_connector);
 }
 
-static struct drm_connector_funcs sti_hdmi_connector_funcs = {
+static const struct drm_connector_funcs sti_hdmi_connector_funcs = {
        .dpms = drm_atomic_helper_connector_dpms,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = sti_hdmi_connector_detect,
@@ -700,18 +701,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
 
        encoder = sti_hdmi_find_encoder(drm_dev);
        if (!encoder)
-               goto err_adapt;
+               return -EINVAL;
 
        connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
        if (!connector)
-               goto err_adapt;
-
+               return -EINVAL;
 
        connector->hdmi = hdmi;
 
        bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
        if (!bridge)
-               goto err_adapt;
+               return -EINVAL;
 
        bridge->driver_private = hdmi;
        bridge->funcs = &sti_hdmi_bridge_funcs;
@@ -748,8 +748,7 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
        drm_connector_unregister(drm_connector);
 err_connector:
        drm_connector_cleanup(drm_connector);
-err_adapt:
-       put_device(&hdmi->ddc_adapt->dev);
+
        return -EINVAL;
 }
 
@@ -794,13 +793,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
 
        ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
        if (ddc) {
-               hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
-               if (!hdmi->ddc_adapt) {
-                       of_node_put(ddc);
-                       return -EPROBE_DEFER;
-               }
-
+               hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
                of_node_put(ddc);
+               if (!hdmi->ddc_adapt)
+                       return -EPROBE_DEFER;
        }
 
        hdmi->dev = pdev->dev;
@@ -809,24 +805,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
        if (!res) {
                DRM_ERROR("Invalid hdmi resource\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto release_adapter;
        }
        hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-       if (!hdmi->regs)
-               return -ENOMEM;
+       if (!hdmi->regs) {
+               ret = -ENOMEM;
+               goto release_adapter;
+       }
 
        if (of_device_is_compatible(np, "st,stih416-hdmi")) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                                                   "syscfg");
                if (!res) {
                        DRM_ERROR("Invalid syscfg resource\n");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto release_adapter;
                }
                hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
                                                    resource_size(res));
-               if (!hdmi->syscfg)
-                       return -ENOMEM;
-
+               if (!hdmi->syscfg) {
+                       ret = -ENOMEM;
+                       goto release_adapter;
+               }
        }
 
        hdmi->phy_ops = (struct hdmi_phy_ops *)
@@ -836,25 +837,29 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        hdmi->clk_pix = devm_clk_get(dev, "pix");
        if (IS_ERR(hdmi->clk_pix)) {
                DRM_ERROR("Cannot get hdmi_pix clock\n");
-               return PTR_ERR(hdmi->clk_pix);
+               ret = PTR_ERR(hdmi->clk_pix);
+               goto release_adapter;
        }
 
        hdmi->clk_tmds = devm_clk_get(dev, "tmds");
        if (IS_ERR(hdmi->clk_tmds)) {
                DRM_ERROR("Cannot get hdmi_tmds clock\n");
-               return PTR_ERR(hdmi->clk_tmds);
+               ret = PTR_ERR(hdmi->clk_tmds);
+               goto release_adapter;
        }
 
        hdmi->clk_phy = devm_clk_get(dev, "phy");
        if (IS_ERR(hdmi->clk_phy)) {
                DRM_ERROR("Cannot get hdmi_phy clock\n");
-               return PTR_ERR(hdmi->clk_phy);
+               ret = PTR_ERR(hdmi->clk_phy);
+               goto release_adapter;
        }
 
        hdmi->clk_audio = devm_clk_get(dev, "audio");
        if (IS_ERR(hdmi->clk_audio)) {
                DRM_ERROR("Cannot get hdmi_audio clock\n");
-               return PTR_ERR(hdmi->clk_audio);
+               ret = PTR_ERR(hdmi->clk_audio);
+               goto release_adapter;
        }
 
        hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
@@ -867,7 +872,7 @@ static int sti_hdmi_probe(struct platform_device *pdev)
                        hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
        if (ret) {
                DRM_ERROR("Failed to register HDMI interrupt\n");
-               return ret;
+               goto release_adapter;
        }
 
        hdmi->reset = devm_reset_control_get(dev, "hdmi");
@@ -878,16 +883,20 @@ static int sti_hdmi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, hdmi);
 
        return component_add(&pdev->dev, &sti_hdmi_ops);
+
+ release_adapter:
+       i2c_put_adapter(hdmi->ddc_adapt);
+
+       return ret;
 }
 
 static int sti_hdmi_remove(struct platform_device *pdev)
 {
        struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
 
-       if (hdmi->ddc_adapt)
-               put_device(&hdmi->ddc_adapt->dev);
-
+       i2c_put_adapter(hdmi->ddc_adapt);
        component_del(&pdev->dev, &sti_hdmi_ops);
+
        return 0;
 }
 
@@ -901,8 +910,6 @@ struct platform_driver sti_hdmi_driver = {
        .remove = sti_hdmi_remove,
 };
 
-module_platform_driver(sti_hdmi_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 7c8f9b8bfae10a27339b6693b462406500639c6c..ea0690bc77d5f72587ede24e1d1936d6dbd00578 100644 (file)
@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
        memset(hqvdp->hqvdp_cmd, 0, size);
 }
 
+static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
+{
+       /* Configure Plugs (same for RD & WR) */
+       writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
+       writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
+       writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
+       writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
+       writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
+       writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
+       writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
+
+       writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
+       writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
+       writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
+       writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
+       writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
+       writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
+       writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
+}
+
+/**
+ * sti_hqvdp_start_xp70
+ * @hqvdp: hqvdp pointer
+ *
+ * Run the xP70 initialization sequence
+ */
+static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
+{
+       const struct firmware *firmware;
+       u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
+       u8 *data;
+       int i;
+       struct fw_header {
+               int rd_size;
+               int wr_size;
+               int pmem_size;
+               int dmem_size;
+       } *header;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (hqvdp->xp70_initialized) {
+               DRM_INFO("HQVDP XP70 already initialized\n");
+               return;
+       }
+
+       /* Request firmware */
+       if (request_firmware(&firmware, HQVDP_FMW_NAME, hqvdp->dev)) {
+               DRM_ERROR("Can't get HQVDP firmware\n");
+               return;
+       }
+
+       /* Check firmware parts */
+       if (!firmware) {
+               DRM_ERROR("Firmware not available\n");
+               return;
+       }
+
+       header = (struct fw_header *)firmware->data;
+       if (firmware->size < sizeof(*header)) {
+               DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
+               goto out;
+       }
+       if ((sizeof(*header) + header->rd_size + header->wr_size +
+               header->pmem_size + header->dmem_size) != firmware->size) {
+               DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
+                         sizeof(*header), header->rd_size, header->wr_size,
+                         header->pmem_size, header->dmem_size,
+                         firmware->size);
+               goto out;
+       }
+
+       data = (u8 *)firmware->data;
+       data += sizeof(*header);
+       fw_rd_plug = (void *)data;
+       data += header->rd_size;
+       fw_wr_plug = (void *)data;
+       data += header->wr_size;
+       fw_pmem = (void *)data;
+       data += header->pmem_size;
+       fw_dmem = (void *)data;
+
+       /* Enable clock */
+       if (clk_prepare_enable(hqvdp->clk))
+               DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
+
+       /* Reset */
+       writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
+
+       for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
+               if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
+                               & STARTUP_CTRL1_RST_DONE)
+                       break;
+               msleep(POLL_DELAY_MS);
+       }
+       if (i == POLL_MAX_ATTEMPT) {
+               DRM_ERROR("Could not reset\n");
+               goto out;
+       }
+
+       /* Init Read & Write plugs */
+       for (i = 0; i < header->rd_size / 4; i++)
+               writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
+       for (i = 0; i < header->wr_size / 4; i++)
+               writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
+
+       sti_hqvdp_init_plugs(hqvdp);
+
+       /* Authorize Idle Mode */
+       writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
+
+       /* Prevent VTG interruption during the boot */
+       writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
+       writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
+
+       /* Download PMEM & DMEM */
+       for (i = 0; i < header->pmem_size / 4; i++)
+               writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
+       for (i = 0; i < header->dmem_size / 4; i++)
+               writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
+
+       /* Enable fetch */
+       writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
+
+       /* Wait end of boot */
+       for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
+               if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
+                               & INFO_XP70_FW_READY)
+                       break;
+               msleep(POLL_DELAY_MS);
+       }
+       if (i == POLL_MAX_ATTEMPT) {
+               DRM_ERROR("Could not boot\n");
+               goto out;
+       }
+
+       /* Launch Vsync */
+       writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
+
+       DRM_INFO("HQVDP XP70 initialized\n");
+
+       hqvdp->xp70_initialized = true;
+
+out:
+       release_firmware(firmware);
+}
+
 static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
                                    struct drm_plane_state *oldstate)
 {
@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
        sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
 
        if (first_prepare) {
+               /* Start HQVDP XP70 coprocessor */
+               sti_hqvdp_start_xp70(hqvdp);
+
                /* Prevent VTG shutdown */
                if (clk_prepare_enable(hqvdp->clk_pix_main)) {
                        DRM_ERROR("Failed to prepare/enable pix main clk\n");
@@ -763,7 +913,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
                /* Register VTG Vsync callback to handle bottom fields */
                if (sti_vtg_register_client(hqvdp->vtg,
                                            &hqvdp->vtg_nb,
-                                           mixer->id)) {
+                                           crtc)) {
                        DRM_ERROR("Cannot register VTG notifier\n");
                        return;
                }
@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
        return &hqvdp->plane.drm_plane;
 }
 
-static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
-{
-       /* Configure Plugs (same for RD & WR) */
-       writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
-       writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
-       writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
-       writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
-       writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
-       writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
-       writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
-
-       writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
-       writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
-       writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
-       writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
-       writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
-       writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
-       writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
-}
-
-/**
- * sti_hqvdp_start_xp70
- * @firmware: firmware found
- * @ctxt:     hqvdp structure
- *
- * Run the xP70 initialization sequence
- */
-static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
-{
-       struct sti_hqvdp *hqvdp = ctxt;
-       u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
-       u8 *data;
-       int i;
-       struct fw_header {
-               int rd_size;
-               int wr_size;
-               int pmem_size;
-               int dmem_size;
-       } *header;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       if (hqvdp->xp70_initialized) {
-               DRM_INFO("HQVDP XP70 already initialized\n");
-               return;
-       }
-
-       /* Check firmware parts */
-       if (!firmware) {
-               DRM_ERROR("Firmware not available\n");
-               return;
-       }
-
-       header = (struct fw_header *) firmware->data;
-       if (firmware->size < sizeof(*header)) {
-               DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
-               goto out;
-       }
-       if ((sizeof(*header) + header->rd_size + header->wr_size +
-               header->pmem_size + header->dmem_size) != firmware->size) {
-               DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
-                          sizeof(*header), header->rd_size, header->wr_size,
-                          header->pmem_size, header->dmem_size,
-                          firmware->size);
-               goto out;
-       }
-
-       data = (u8 *) firmware->data;
-       data += sizeof(*header);
-       fw_rd_plug = (void *) data;
-       data += header->rd_size;
-       fw_wr_plug = (void *) data;
-       data += header->wr_size;
-       fw_pmem = (void *) data;
-       data += header->pmem_size;
-       fw_dmem = (void *) data;
-
-       /* Enable clock */
-       if (clk_prepare_enable(hqvdp->clk))
-               DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
-
-       /* Reset */
-       writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
-
-       for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
-               if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
-                               & STARTUP_CTRL1_RST_DONE)
-                       break;
-               msleep(POLL_DELAY_MS);
-       }
-       if (i == POLL_MAX_ATTEMPT) {
-               DRM_ERROR("Could not reset\n");
-               goto out;
-       }
-
-       /* Init Read & Write plugs */
-       for (i = 0; i < header->rd_size / 4; i++)
-               writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
-       for (i = 0; i < header->wr_size / 4; i++)
-               writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
-
-       sti_hqvdp_init_plugs(hqvdp);
-
-       /* Authorize Idle Mode */
-       writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
-
-       /* Prevent VTG interruption during the boot */
-       writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
-       writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
-
-       /* Download PMEM & DMEM */
-       for (i = 0; i < header->pmem_size / 4; i++)
-               writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
-       for (i = 0; i < header->dmem_size / 4; i++)
-               writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
-
-       /* Enable fetch */
-       writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
-
-       /* Wait end of boot */
-       for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
-               if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
-                               & INFO_XP70_FW_READY)
-                       break;
-               msleep(POLL_DELAY_MS);
-       }
-       if (i == POLL_MAX_ATTEMPT) {
-               DRM_ERROR("Could not boot\n");
-               goto out;
-       }
-
-       /* Launch Vsync */
-       writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
-
-       DRM_INFO("HQVDP XP70 initialized\n");
-
-       hqvdp->xp70_initialized = true;
-
-out:
-       release_firmware(firmware);
-}
-
 int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
 {
        struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
        struct drm_device *drm_dev = data;
        struct drm_plane *plane;
-       int err;
 
        DRM_DEBUG_DRIVER("\n");
 
        hqvdp->drm_dev = drm_dev;
 
-       /* Request for firmware */
-       err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               HQVDP_FMW_NAME, hqvdp->dev,
-                               GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70);
-       if (err) {
-               DRM_ERROR("Can't get HQVDP firmware\n");
-               return err;
-       }
-
        /* Create HQVDP plane once xp70 is initialized */
        plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
        if (!plane)
@@ -1090,8 +1088,6 @@ struct platform_driver sti_hqvdp_driver = {
        .remove = sti_hqvdp_remove,
 };
 
-module_platform_driver(sti_hqvdp_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 0182e936500427e8fd798251c6dccdd340b87495..49db835dce036a3a78fc9cb13e1fdd5173fc7d7a 100644 (file)
 #include "sti_mixer.h"
 #include "sti_vtg.h"
 
+/* Module parameter to set the background color of the mixer */
+static unsigned int bkg_color = 0x000000;
+MODULE_PARM_DESC(bkgcolor, "Value of the background color 0xRRGGBB");
+module_param_named(bkgcolor, bkg_color, int, 0644);
+
 /* Identity: G=Y , B=Cb , R=Cr */
 static const u32 mixerColorSpaceMatIdentity[] = {
        0x10000000, 0x00000000, 0x10000000, 0x00001000,
@@ -58,7 +63,6 @@ const char *sti_mixer_to_str(struct sti_mixer *mixer)
                return "<UNKNOWN MIXER>";
        }
 }
-EXPORT_SYMBOL(sti_mixer_to_str);
 
 static inline u32 sti_mixer_reg_read(struct sti_mixer *mixer, u32 reg_id)
 {
@@ -81,11 +85,9 @@ void sti_mixer_set_background_status(struct sti_mixer *mixer, bool enable)
 }
 
 static void sti_mixer_set_background_color(struct sti_mixer *mixer,
-                                          u8 red, u8 green, u8 blue)
+                                          unsigned int rgb)
 {
-       u32 val = (red << 16) | (green << 8) | blue;
-
-       sti_mixer_reg_write(mixer, GAM_MIXER_BKC, val);
+       sti_mixer_reg_write(mixer, GAM_MIXER_BKC, rgb);
 }
 
 static void sti_mixer_set_background_area(struct sti_mixer *mixer,
@@ -175,7 +177,7 @@ int sti_mixer_active_video_area(struct sti_mixer *mixer,
        sti_mixer_reg_write(mixer, GAM_MIXER_AVO, ydo << 16 | xdo);
        sti_mixer_reg_write(mixer, GAM_MIXER_AVS, yds << 16 | xds);
 
-       sti_mixer_set_background_color(mixer, 0xFF, 0, 0);
+       sti_mixer_set_background_color(mixer, bkg_color);
 
        sti_mixer_set_background_area(mixer, mode);
        sti_mixer_set_background_status(mixer, true);
index d5c5e91f2956038d2daa3b180051c635bfd6d0e4..2e5c751910c579b70f90836d9a7973bd2f086921 100644 (file)
@@ -42,7 +42,6 @@ const char *sti_plane_to_str(struct sti_plane *plane)
                return "<UNKNOWN PLANE>";
        }
 }
-EXPORT_SYMBOL(sti_plane_to_str);
 
 static void sti_plane_destroy(struct drm_plane *drm_plane)
 {
@@ -108,7 +107,6 @@ void sti_plane_init_property(struct sti_plane *plane,
                         plane->drm_plane.base.id,
                         sti_plane_to_str(plane), plane->zorder);
 }
-EXPORT_SYMBOL(sti_plane_init_property);
 
 struct drm_plane_funcs sti_plane_helpers_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
@@ -119,4 +117,3 @@ struct drm_plane_funcs sti_plane_helpers_funcs = {
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
 };
-EXPORT_SYMBOL(sti_plane_helpers_funcs);
index c1aac8e66fb5024a626aa5a37bf99264beb0d870..c8a4c5dae2b6f2010365d4e63c43ec2b4d8c8659 100644 (file)
@@ -735,8 +735,6 @@ struct platform_driver sti_tvout_driver = {
        .remove = sti_tvout_remove,
 };
 
-module_platform_driver(sti_tvout_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index 97bcdac23ae1f0733d87b3cc6f3b071834d1bdba..b1eb0d77630dfce30ee13373371edfbb32c10dad 100644 (file)
@@ -216,8 +216,6 @@ struct platform_driver sti_vtac_driver = {
        .remove = sti_vtac_remove,
 };
 
-module_platform_driver(sti_vtac_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index aa809713770166537db8f124dff3a2934e7492c9..d56630c60039fead79ca37f1ed52b7614f9e8aee 100644 (file)
@@ -79,7 +79,7 @@ LIST_HEAD(vtg_lookup);
  * @irq: VTG irq
  * @type: VTG type (main or aux)
  * @notifier_list: notifier callback
- * @crtc_id: the crtc id for vblank event
+ * @crtc: the CRTC for vblank event
  * @slave: slave vtg
  * @link: List node to link the structure in lookup list
  */
@@ -90,7 +90,7 @@ struct sti_vtg {
        int irq;
        u32 irq_status;
        struct raw_notifier_head notifier_list;
-       int crtc_id;
+       struct drm_crtc *crtc;
        struct sti_vtg *slave;
        struct list_head link;
 };
@@ -110,7 +110,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np)
        }
        return NULL;
 }
-EXPORT_SYMBOL(of_vtg_find);
 
 static void vtg_reset(struct sti_vtg *vtg)
 {
@@ -242,7 +241,6 @@ void sti_vtg_set_config(struct sti_vtg *vtg,
        else
                vtg_enable_irq(vtg);
 }
-EXPORT_SYMBOL(sti_vtg_set_config);
 
 /**
  * sti_vtg_get_line_number
@@ -265,7 +263,6 @@ u32 sti_vtg_get_line_number(struct drm_display_mode mode, int y)
 
        return start_line + y;
 }
-EXPORT_SYMBOL(sti_vtg_get_line_number);
 
 /**
  * sti_vtg_get_pixel_number
@@ -281,18 +278,16 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
 {
        return mode.htotal - mode.hsync_start + x;
 }
-EXPORT_SYMBOL(sti_vtg_get_pixel_number);
 
-int sti_vtg_register_client(struct sti_vtg *vtg,
-               struct notifier_block *nb, int crtc_id)
+int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
+                           struct drm_crtc *crtc)
 {
        if (vtg->slave)
-               return sti_vtg_register_client(vtg->slave, nb, crtc_id);
+               return sti_vtg_register_client(vtg->slave, nb, crtc);
 
-       vtg->crtc_id = crtc_id;
+       vtg->crtc = crtc;
        return raw_notifier_chain_register(&vtg->notifier_list, nb);
 }
-EXPORT_SYMBOL(sti_vtg_register_client);
 
 int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
 {
@@ -301,7 +296,6 @@ int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
 
        return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
 }
-EXPORT_SYMBOL(sti_vtg_unregister_client);
 
 static irqreturn_t vtg_irq_thread(int irq, void *arg)
 {
@@ -311,7 +305,7 @@ static irqreturn_t vtg_irq_thread(int irq, void *arg)
        event = (vtg->irq_status & VTG_IRQ_TOP) ?
                VTG_TOP_FIELD_EVENT : VTG_BOTTOM_FIELD_EVENT;
 
-       raw_notifier_call_chain(&vtg->notifier_list, event, &vtg->crtc_id);
+       raw_notifier_call_chain(&vtg->notifier_list, event, vtg->crtc);
 
        return IRQ_HANDLED;
 }
@@ -406,8 +400,6 @@ struct platform_driver sti_vtg_driver = {
        .remove = vtg_remove,
 };
 
-module_platform_driver(sti_vtg_driver);
-
 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
 MODULE_LICENSE("GPL");
index e84d23f1f57ff71912eac3759f0691625eb64776..cd2439f89d05d6b183f36a529526b3fa33d46b86 100644 (file)
@@ -17,8 +17,8 @@ struct notifier_block;
 struct sti_vtg *of_vtg_find(struct device_node *np);
 void sti_vtg_set_config(struct sti_vtg *vtg,
                const struct drm_display_mode *mode);
-int sti_vtg_register_client(struct sti_vtg *vtg,
-               struct notifier_block *nb, int crtc_id);
+int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
+                           struct drm_crtc *crtc);
 int sti_vtg_unregister_client(struct sti_vtg *vtg,
                struct notifier_block *nb);
 
index 7a9f4768591eabe54877327bbf6c1cc220c6d525..265064c62d493b54023947d49597852a16328a5f 100644 (file)
@@ -168,7 +168,7 @@ static int vc4_get_clock_select(struct drm_crtc *crtc)
        struct drm_connector *connector;
 
        drm_for_each_connector(connector, crtc->dev) {
-               if (connector && connector->state->crtc == crtc) {
+               if (connector->state->crtc == crtc) {
                        struct drm_encoder *encoder = connector->encoder;
                        struct vc4_encoder *vc4_encoder =
                                to_vc4_encoder(encoder);
@@ -401,7 +401,8 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
                dlist_next++;
 
                HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
-                         (u32 *)vc4_crtc->dlist - (u32 *)vc4->hvs->dlist);
+                         (u32 __iomem *)vc4_crtc->dlist -
+                         (u32 __iomem *)vc4->hvs->dlist);
 
                /* Make the next display list start after ours. */
                vc4_crtc->dlist_size -= (dlist_next - vc4_crtc->dlist);
@@ -591,14 +592,14 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
         * that will take too much.
         */
        primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
-       if (!primary_plane) {
+       if (IS_ERR(primary_plane)) {
                dev_err(dev, "failed to construct primary plane\n");
                ret = PTR_ERR(primary_plane);
                goto err;
        }
 
        cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
-       if (!cursor_plane) {
+       if (IS_ERR(cursor_plane)) {
                dev_err(dev, "failed to construct cursor plane\n");
                ret = PTR_ERR(cursor_plane);
                goto err_primary;
index 6e730605edccc01de7ff01fd6e3b7ca58f62ec6d..d5db9e0f3b736ee1acc07888f59c4650aaa84287 100644 (file)
@@ -259,7 +259,6 @@ static struct platform_driver vc4_platform_driver = {
        .remove         = vc4_platform_drm_remove,
        .driver         = {
                .name   = "vc4-drm",
-               .owner  = THIS_MODULE,
                .of_match_table = vc4_of_match,
        },
 };
index ab1673f672a4ec9c88e46e008de64aeb0dded415..8098c5b21ba447c43a16c7a62b9a4de0590abe1f 100644 (file)
@@ -75,10 +75,10 @@ void vc4_hvs_dump_state(struct drm_device *dev)
        for (i = 0; i < 64; i += 4) {
                DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
                         i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
-                        ((uint32_t *)vc4->hvs->dlist)[i + 0],
-                        ((uint32_t *)vc4->hvs->dlist)[i + 1],
-                        ((uint32_t *)vc4->hvs->dlist)[i + 2],
-                        ((uint32_t *)vc4->hvs->dlist)[i + 3]);
+                        readl((u32 __iomem *)vc4->hvs->dlist + i + 0),
+                        readl((u32 __iomem *)vc4->hvs->dlist + i + 1),
+                        readl((u32 __iomem *)vc4->hvs->dlist + i + 2),
+                        readl((u32 __iomem *)vc4->hvs->dlist + i + 3));
        }
 }
 
index cdd8b10c014742cb8079837e2723163afb8d04c1..887f3caad0be6b6fd115b4e9430abfd3aeadd53f 100644 (file)
@@ -70,7 +70,7 @@ static bool plane_enabled(struct drm_plane_state *state)
        return state->fb && state->crtc;
 }
 
-struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
+static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
 {
        struct vc4_plane_state *vc4_state;
 
@@ -97,8 +97,8 @@ struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
        return &vc4_state->base;
 }
 
-void vc4_plane_destroy_state(struct drm_plane *plane,
-                            struct drm_plane_state *state)
+static void vc4_plane_destroy_state(struct drm_plane *plane,
+                                   struct drm_plane_state *state)
 {
        struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
 
@@ -108,7 +108,7 @@ void vc4_plane_destroy_state(struct drm_plane *plane,
 }
 
 /* Called during init to allocate the plane's atomic state. */
-void vc4_plane_reset(struct drm_plane *plane)
+static void vc4_plane_reset(struct drm_plane *plane)
 {
        struct vc4_plane_state *vc4_state;
 
@@ -157,6 +157,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
        int crtc_w = state->crtc_w;
        int crtc_h = state->crtc_h;
 
+       if (state->crtc_w << 16 != state->src_w ||
+           state->crtc_h << 16 != state->src_h) {
+               /* We don't support scaling yet, which involves
+                * allocating the LBM memory for scaling temporary
+                * storage, and putting filter kernels in the HVS
+                * context.
+                */
+               return -EINVAL;
+       }
+
        if (crtc_x < 0) {
                offset += drm_format_plane_cpp(fb->pixel_format, 0) * -crtc_x;
                crtc_w += crtc_x;
index 8b29949507d1692f436b1db5045ca7ed4b8d54f3..01a4f05c16421b63a09737ad3eb4a4fb249259ae 100644 (file)
@@ -2481,7 +2481,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
                if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
                        if (features->touch_max)
                                features->device_type |= WACOM_DEVICETYPE_TOUCH;
-                       if (features->type >= INTUOSHT || features->type <= BAMBOO_PT)
+                       if (features->type >= INTUOSHT && features->type <= BAMBOO_PT)
                                features->device_type |= WACOM_DEVICETYPE_PAD;
 
                        features->x_max = 4096;
@@ -3213,7 +3213,8 @@ static const struct wacom_features wacom_features_0x32F =
          WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x336 =
        { "Wacom DTU1141", 23472, 13203, 1023, 0,
-         DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+         DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+         WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x57 =
        { "Wacom DTK2241", 95640, 54060, 2047, 63,
          DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
index 842b0043ad9477160194a7c7a94b03f7ab06d5a1..8f59f057cdf4a336cf29cd32803dff2b50143be2 100644 (file)
@@ -324,6 +324,7 @@ config SENSORS_APPLESMC
 config SENSORS_ARM_SCPI
        tristate "ARM SCPI Sensors"
        depends on ARM_SCPI_PROTOCOL
+       depends on THERMAL || !THERMAL_OF
        help
          This driver provides support for temperature, voltage, current
          and power sensors available on ARM Ltd's SCP based platforms. The
@@ -1471,6 +1472,7 @@ config SENSORS_INA209
 config SENSORS_INA2XX
        tristate "Texas Instruments INA219 and compatibles"
        depends on I2C
+       select REGMAP_I2C
        help
          If you say yes here you get support for INA219, INA220, INA226,
          INA230, and INA231 power monitor chips.
index 1f5e956941b1326c6f590b62354bffd40e29ea95..0af7fd311979d25d0684e585ec92f9a65169bdaa 100644 (file)
@@ -537,7 +537,7 @@ static int applesmc_init_index(struct applesmc_registers *s)
 static int applesmc_init_smcreg_try(void)
 {
        struct applesmc_registers *s = &smcreg;
-       bool left_light_sensor, right_light_sensor;
+       bool left_light_sensor = 0, right_light_sensor = 0;
        unsigned int count;
        u8 tmp[1];
        int ret;
index 2c1241bbf9affdbf616a357d3b95c7f7c9963669..7e20567bc36912ada47687716405733e1372bc8a 100644 (file)
@@ -117,7 +117,7 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
        struct scpi_ops *scpi_ops;
        struct device *hwdev, *dev = &pdev->dev;
        struct scpi_sensors *scpi_sensors;
-       int ret;
+       int ret, idx;
 
        scpi_ops = get_scpi_ops();
        if (!scpi_ops)
@@ -146,8 +146,8 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
 
        scpi_sensors->scpi_ops = scpi_ops;
 
-       for (i = 0; i < nr_sensors; i++) {
-               struct sensor_data *sensor = &scpi_sensors->data[i];
+       for (i = 0, idx = 0; i < nr_sensors; i++) {
+               struct sensor_data *sensor = &scpi_sensors->data[idx];
 
                ret = scpi_ops->sensor_get_info(i, &sensor->info);
                if (ret)
@@ -183,7 +183,7 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
                        num_power++;
                        break;
                default:
-                       break;
+                       continue;
                }
 
                sensor->dev_attr_input.attr.mode = S_IRUGO;
@@ -194,11 +194,12 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
                sensor->dev_attr_label.show = scpi_show_label;
                sensor->dev_attr_label.attr.name = sensor->label;
 
-               scpi_sensors->attrs[i << 1] = &sensor->dev_attr_input.attr;
-               scpi_sensors->attrs[(i << 1) + 1] = &sensor->dev_attr_label.attr;
+               scpi_sensors->attrs[idx << 1] = &sensor->dev_attr_input.attr;
+               scpi_sensors->attrs[(idx << 1) + 1] = &sensor->dev_attr_label.attr;
 
-               sysfs_attr_init(scpi_sensors->attrs[i << 1]);
-               sysfs_attr_init(scpi_sensors->attrs[(i << 1) + 1]);
+               sysfs_attr_init(scpi_sensors->attrs[idx << 1]);
+               sysfs_attr_init(scpi_sensors->attrs[(idx << 1) + 1]);
+               idx++;
        }
 
        scpi_sensors->group.attrs = scpi_sensors->attrs;
@@ -236,8 +237,8 @@ static int scpi_hwmon_probe(struct platform_device *pdev)
 
                zone->sensor_id = i;
                zone->scpi_sensors = scpi_sensors;
-               zone->tzd = thermal_zone_of_sensor_register(dev, i, zone,
-                                                           &scpi_sensor_ops);
+               zone->tzd = thermal_zone_of_sensor_register(dev,
+                               sensor->info.sensor_id, zone, &scpi_sensor_ops);
                /*
                 * The call to thermal_zone_of_sensor_register returns
                 * an error for sensors that are not associated with
index 6498a9dbb7bd184802c6f270548c417b24e38e2d..11ab6d01adf63d1490c8474801d358ada4f657a8 100644 (file)
@@ -76,9 +76,10 @@ to_stp_policy_node(struct config_item *item)
                NULL;
 }
 
-static ssize_t stp_policy_node_masters_show(struct stp_policy_node *policy_node,
-                                           char *page)
+static ssize_t
+stp_policy_node_masters_show(struct config_item *item, char *page)
 {
+       struct stp_policy_node *policy_node = to_stp_policy_node(item);
        ssize_t count;
 
        count = sprintf(page, "%u %u\n", policy_node->first_master,
@@ -88,9 +89,10 @@ static ssize_t stp_policy_node_masters_show(struct stp_policy_node *policy_node,
 }
 
 static ssize_t
-stp_policy_node_masters_store(struct stp_policy_node *policy_node,
-                             const char *page, size_t count)
+stp_policy_node_masters_store(struct config_item *item, const char *page,
+                             size_t count)
 {
+       struct stp_policy_node *policy_node = to_stp_policy_node(item);
        unsigned int first, last;
        struct stm_device *stm;
        char *p = (char *)page;
@@ -123,8 +125,9 @@ stp_policy_node_masters_store(struct stp_policy_node *policy_node,
 }
 
 static ssize_t
-stp_policy_node_channels_show(struct stp_policy_node *policy_node, char *page)
+stp_policy_node_channels_show(struct config_item *item, char *page)
 {
+       struct stp_policy_node *policy_node = to_stp_policy_node(item);
        ssize_t count;
 
        count = sprintf(page, "%u %u\n", policy_node->first_channel,
@@ -134,9 +137,10 @@ stp_policy_node_channels_show(struct stp_policy_node *policy_node, char *page)
 }
 
 static ssize_t
-stp_policy_node_channels_store(struct stp_policy_node *policy_node,
-                              const char *page, size_t count)
+stp_policy_node_channels_store(struct config_item *item, const char *page,
+                              size_t count)
 {
+       struct stp_policy_node *policy_node = to_stp_policy_node(item);
        unsigned int first, last;
        struct stm_device *stm;
        char *p = (char *)page;
@@ -171,71 +175,16 @@ static void stp_policy_node_release(struct config_item *item)
        kfree(to_stp_policy_node(item));
 }
 
-struct stp_policy_node_attribute {
-       struct configfs_attribute       attr;
-       ssize_t (*show)(struct stp_policy_node *, char *);
-       ssize_t (*store)(struct stp_policy_node *, const char *, size_t);
-};
-
-static ssize_t stp_policy_node_attr_show(struct config_item *item,
-                                        struct configfs_attribute *attr,
-                                        char *page)
-{
-       struct stp_policy_node *policy_node = to_stp_policy_node(item);
-       struct stp_policy_node_attribute *pn_attr =
-               container_of(attr, struct stp_policy_node_attribute, attr);
-       ssize_t count = 0;
-
-       if (pn_attr->show)
-               count = pn_attr->show(policy_node, page);
-
-       return count;
-}
-
-static ssize_t stp_policy_node_attr_store(struct config_item *item,
-                                         struct configfs_attribute *attr,
-                                         const char *page, size_t len)
-{
-       struct stp_policy_node *policy_node = to_stp_policy_node(item);
-       struct stp_policy_node_attribute *pn_attr =
-               container_of(attr, struct stp_policy_node_attribute, attr);
-       ssize_t count = -EINVAL;
-
-       if (pn_attr->store)
-               count = pn_attr->store(policy_node, page, len);
-
-       return count;
-}
-
 static struct configfs_item_operations stp_policy_node_item_ops = {
        .release                = stp_policy_node_release,
-       .show_attribute         = stp_policy_node_attr_show,
-       .store_attribute        = stp_policy_node_attr_store,
 };
 
-static struct stp_policy_node_attribute stp_policy_node_attr_range = {
-       .attr   = {
-               .ca_owner = THIS_MODULE,
-               .ca_name = "masters",
-               .ca_mode = S_IRUGO | S_IWUSR,
-       },
-       .show   = stp_policy_node_masters_show,
-       .store  = stp_policy_node_masters_store,
-};
-
-static struct stp_policy_node_attribute stp_policy_node_attr_channels = {
-       .attr   = {
-               .ca_owner = THIS_MODULE,
-               .ca_name = "channels",
-               .ca_mode = S_IRUGO | S_IWUSR,
-       },
-       .show   = stp_policy_node_channels_show,
-       .store  = stp_policy_node_channels_store,
-};
+CONFIGFS_ATTR(stp_policy_node_, masters);
+CONFIGFS_ATTR(stp_policy_node_, channels);
 
 static struct configfs_attribute *stp_policy_node_attrs[] = {
-       &stp_policy_node_attr_range.attr,
-       &stp_policy_node_attr_channels.attr,
+       &stp_policy_node_attr_masters,
+       &stp_policy_node_attr_channels,
        NULL,
 };
 
@@ -298,20 +247,8 @@ static struct config_item_type stp_policy_node_type = {
 /*
  * Root group: policies.
  */
-static struct configfs_attribute stp_policy_attr_device = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "device",
-       .ca_mode = S_IRUGO,
-};
-
-static struct configfs_attribute *stp_policy_attrs[] = {
-       &stp_policy_attr_device,
-       NULL,
-};
-
-static ssize_t stp_policy_attr_show(struct config_item *item,
-                                   struct configfs_attribute *attr,
-                                   char *page)
+static ssize_t stp_policy_device_show(struct config_item *item,
+                                     char *page)
 {
        struct stp_policy *policy = to_stp_policy(item);
        ssize_t count;
@@ -324,6 +261,13 @@ static ssize_t stp_policy_attr_show(struct config_item *item,
        return count;
 }
 
+CONFIGFS_ATTR_RO(stp_policy_, device);
+
+static struct configfs_attribute *stp_policy_attrs[] = {
+       &stp_policy_attr_device,
+       NULL,
+};
+
 void stp_policy_unbind(struct stp_policy *policy)
 {
        struct stm_device *stm = policy->stm;
@@ -350,7 +294,6 @@ static void stp_policy_release(struct config_item *item)
 
 static struct configfs_item_operations stp_policy_item_ops = {
        .release                = stp_policy_release,
-       .show_attribute         = stp_policy_attr_show,
 };
 
 static struct configfs_group_operations stp_policy_group_ops = {
index e24c2b680b475880dd56d0bfb6f2691c00d26801..7b0aa82ea38b2e7521650e6c9a1cab5b25ac8ee4 100644 (file)
@@ -126,6 +126,7 @@ config I2C_I801
            Sunrise Point-LP (PCH)
            DNV (SOC)
            Broxton (SOC)
+           Lewisburg (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
index c306751ceadb44c24757b02281de24779038b1cb..f62d69799a9c55b0f79e2de5e29ec9a09b257c98 100644 (file)
@@ -62,6 +62,8 @@
  * Sunrise Point-LP (PCH)      0x9d23  32      hard    yes     yes     yes
  * DNV (SOC)                   0x19df  32      hard    yes     yes     yes
  * Broxton (SOC)               0x5ad4  32      hard    yes     yes     yes
+ * Lewisburg (PCH)             0xa1a3  32      hard    yes     yes     yes
+ * Lewisburg Supersku (PCH)    0xa223  32      hard    yes     yes     yes
  *
  * Features supported by this driver:
  * Software PEC                                no
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS      0x9d23
 #define PCI_DEVICE_ID_INTEL_DNV_SMBUS                  0x19df
 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS              0x5ad4
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS            0xa1a3
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS       0xa223
 
 struct i801_mux_config {
        char *gpio_chip;
@@ -869,6 +873,8 @@ static const struct pci_device_id i801_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) },
        { 0, }
 };
 
index 1e4d99da41646d98a85340369828bb262c77075f..9bb0b056b25f235085df0e994c7c6584581a5a6d 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/of_device.h>
 #include <linux/of_dma.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/i2c-imx.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
index e23a7b068c601906bb1b245d637b0413c2b2c29f..0b20449e48cfe84bba9a7954c641f72be236e5dc 100644 (file)
@@ -662,8 +662,10 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
 
 static void xiic_start_xfer(struct xiic_i2c *i2c)
 {
-
+       spin_lock(&i2c->lock);
+       xiic_reinit(i2c);
        __xiic_start_xfer(i2c);
+       spin_unlock(&i2c->lock);
 }
 
 static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
index 040af5cc8143f1aff2ce8ebaf0143482ddfeee02..ba8eb087f224655d1853c1192371759cf4d5e9f0 100644 (file)
@@ -715,7 +715,7 @@ static int i2c_device_probe(struct device *dev)
                if (wakeirq > 0 && wakeirq != client->irq)
                        status = dev_pm_set_dedicated_wake_irq(dev, wakeirq);
                else if (client->irq > 0)
-                       status = dev_pm_set_wake_irq(dev, wakeirq);
+                       status = dev_pm_set_wake_irq(dev, client->irq);
                else
                        status = 0;
 
index eea0c79111e7c7e2beb6be21cda21d597833e793..4d960d3b93c0b45c70183ed5f4a218649d0dfb87 100644 (file)
 #define AD7795_CH_AIN1M_AIN1M  8 /* AIN1(-) - AIN1(-) */
 
 /* ID Register Bit Designations (AD7793_REG_ID) */
-#define AD7785_ID              0xB
+#define AD7785_ID              0x3
 #define AD7792_ID              0xA
 #define AD7793_ID              0xB
 #define AD7794_ID              0xF
index 599cde3d03a117358f86defec5dcd10ac25b1ed7..b10f629cc44b5e8aa27b9bde4a5c39fbc3694a5e 100644 (file)
 
 #define DEFAULT_SAMPLE_TIME            1000
 
+/* V at 25°C of 696 mV */
+#define VF610_VTEMP25_3V0              950
+/* V at 25°C of 699 mV */
+#define VF610_VTEMP25_3V3              867
+/* Typical sensor slope coefficient at all temperatures */
+#define VF610_TEMP_SLOPE_COEFF         1840
+
 enum clk_sel {
        VF610_ADCIOC_BUSCLK_SET,
        VF610_ADCIOC_ALTCLK_SET,
@@ -197,6 +204,8 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
                adc_feature->clk_div = 8;
        }
 
+       adck_rate = ipg_rate / adc_feature->clk_div;
+
        /*
         * Determine the long sample time adder value to be used based
         * on the default minimum sample time provided.
@@ -221,7 +230,6 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
         * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
         * LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
         */
-       adck_rate = ipg_rate / info->adc_feature.clk_div;
        for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
                info->sample_freq_avail[i] =
                        adck_rate / (6 + vf610_hw_avgs[i] *
@@ -663,11 +671,13 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
                        break;
                case IIO_TEMP:
                        /*
-                       * Calculate in degree Celsius times 1000
-                       * Using sensor slope of 1.84 mV/°C and
-                       * V at 25°C of 696 mV
-                       */
-                       *val = 25000 - ((int)info->value - 864) * 1000000 / 1840;
+                        * Calculate in degree Celsius times 1000
+                        * Using the typical sensor slope of 1.84 mV/°C
+                        * and VREFH_ADC at 3.3V, V at 25°C of 699 mV
+                        */
+                       *val = 25000 - ((int)info->value - VF610_VTEMP25_3V3) *
+                                       1000000 / VF610_TEMP_SLOPE_COEFF;
+
                        break;
                default:
                        mutex_unlock(&indio_dev->mlock);
index 0370624a35db723a6b6089c99398cca36fc10590..02e636a1c49a7a17bbb2cd19356301c41781710f 100644 (file)
@@ -841,6 +841,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
                        case XADC_REG_VCCINT:
                        case XADC_REG_VCCAUX:
                        case XADC_REG_VREFP:
+                       case XADC_REG_VREFN:
                        case XADC_REG_VCCBRAM:
                        case XADC_REG_VCCPINT:
                        case XADC_REG_VCCPAUX:
index 9e4d2c18b5541b2043e244229aeb393e79e737d4..81ca0081a019b355ce58ce26bf9370c84d48fb7b 100644 (file)
@@ -113,12 +113,16 @@ enum ad5064_type {
        ID_AD5065,
        ID_AD5628_1,
        ID_AD5628_2,
+       ID_AD5629_1,
+       ID_AD5629_2,
        ID_AD5648_1,
        ID_AD5648_2,
        ID_AD5666_1,
        ID_AD5666_2,
        ID_AD5668_1,
        ID_AD5668_2,
+       ID_AD5669_1,
+       ID_AD5669_2,
 };
 
 static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
@@ -291,7 +295,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
        { },
 };
 
-#define AD5064_CHANNEL(chan, addr, bits) {                     \
+#define AD5064_CHANNEL(chan, addr, bits, _shift) {             \
        .type = IIO_VOLTAGE,                                    \
        .indexed = 1,                                           \
        .output = 1,                                            \
@@ -303,36 +307,39 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
                .sign = 'u',                                    \
                .realbits = (bits),                             \
                .storagebits = 16,                              \
-               .shift = 20 - bits,                             \
+               .shift = (_shift),                              \
        },                                                      \
        .ext_info = ad5064_ext_info,                            \
 }
 
-#define DECLARE_AD5064_CHANNELS(name, bits) \
+#define DECLARE_AD5064_CHANNELS(name, bits, shift) \
 const struct iio_chan_spec name[] = { \
-       AD5064_CHANNEL(0, 0, bits), \
-       AD5064_CHANNEL(1, 1, bits), \
-       AD5064_CHANNEL(2, 2, bits), \
-       AD5064_CHANNEL(3, 3, bits), \
-       AD5064_CHANNEL(4, 4, bits), \
-       AD5064_CHANNEL(5, 5, bits), \
-       AD5064_CHANNEL(6, 6, bits), \
-       AD5064_CHANNEL(7, 7, bits), \
+       AD5064_CHANNEL(0, 0, bits, shift), \
+       AD5064_CHANNEL(1, 1, bits, shift), \
+       AD5064_CHANNEL(2, 2, bits, shift), \
+       AD5064_CHANNEL(3, 3, bits, shift), \
+       AD5064_CHANNEL(4, 4, bits, shift), \
+       AD5064_CHANNEL(5, 5, bits, shift), \
+       AD5064_CHANNEL(6, 6, bits, shift), \
+       AD5064_CHANNEL(7, 7, bits, shift), \
 }
 
-#define DECLARE_AD5065_CHANNELS(name, bits) \
+#define DECLARE_AD5065_CHANNELS(name, bits, shift) \
 const struct iio_chan_spec name[] = { \
-       AD5064_CHANNEL(0, 0, bits), \
-       AD5064_CHANNEL(1, 3, bits), \
+       AD5064_CHANNEL(0, 0, bits, shift), \
+       AD5064_CHANNEL(1, 3, bits, shift), \
 }
 
-static DECLARE_AD5064_CHANNELS(ad5024_channels, 12);
-static DECLARE_AD5064_CHANNELS(ad5044_channels, 14);
-static DECLARE_AD5064_CHANNELS(ad5064_channels, 16);
+static DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8);
+static DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6);
+static DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4);
 
-static DECLARE_AD5065_CHANNELS(ad5025_channels, 12);
-static DECLARE_AD5065_CHANNELS(ad5045_channels, 14);
-static DECLARE_AD5065_CHANNELS(ad5065_channels, 16);
+static DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8);
+static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6);
+static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4);
+
+static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4);
+static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0);
 
 static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        [ID_AD5024] = {
@@ -382,6 +389,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
                .channels = ad5024_channels,
                .num_channels = 8,
        },
+       [ID_AD5629_1] = {
+               .shared_vref = true,
+               .internal_vref = 2500000,
+               .channels = ad5629_channels,
+               .num_channels = 8,
+       },
+       [ID_AD5629_2] = {
+               .shared_vref = true,
+               .internal_vref = 5000000,
+               .channels = ad5629_channels,
+               .num_channels = 8,
+       },
        [ID_AD5648_1] = {
                .shared_vref = true,
                .internal_vref = 2500000,
@@ -418,6 +437,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
                .channels = ad5064_channels,
                .num_channels = 8,
        },
+       [ID_AD5669_1] = {
+               .shared_vref = true,
+               .internal_vref = 2500000,
+               .channels = ad5669_channels,
+               .num_channels = 8,
+       },
+       [ID_AD5669_2] = {
+               .shared_vref = true,
+               .internal_vref = 5000000,
+               .channels = ad5669_channels,
+               .num_channels = 8,
+       },
 };
 
 static inline unsigned int ad5064_num_vref(struct ad5064_state *st)
@@ -597,10 +628,16 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
        unsigned int addr, unsigned int val)
 {
        struct i2c_client *i2c = to_i2c_client(st->dev);
+       int ret;
 
        st->data.i2c[0] = (cmd << 4) | addr;
        put_unaligned_be16(val, &st->data.i2c[1]);
-       return i2c_master_send(i2c, st->data.i2c, 3);
+
+       ret = i2c_master_send(i2c, st->data.i2c, 3);
+       if (ret < 0)
+               return ret;
+
+       return 0;
 }
 
 static int ad5064_i2c_probe(struct i2c_client *i2c,
@@ -616,12 +653,12 @@ static int ad5064_i2c_remove(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id ad5064_i2c_ids[] = {
-       {"ad5629-1", ID_AD5628_1},
-       {"ad5629-2", ID_AD5628_2},
-       {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */
-       {"ad5669-1", ID_AD5668_1},
-       {"ad5669-2", ID_AD5668_2},
-       {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */
+       {"ad5629-1", ID_AD5629_1},
+       {"ad5629-2", ID_AD5629_2},
+       {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */
+       {"ad5669-1", ID_AD5669_1},
+       {"ad5669-2", ID_AD5669_2},
+       {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */
        {}
 };
 MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
index 12128d1ca570fc4dd93461219628b6ab6461d95d..71991b5c0658d05fe728f797573b08843e51d9ad 100644 (file)
@@ -50,10 +50,10 @@ static int si7020_read_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = i2c_smbus_read_word_data(*client,
-                                              chan->type == IIO_TEMP ?
-                                              SI7020CMD_TEMP_HOLD :
-                                              SI7020CMD_RH_HOLD);
+               ret = i2c_smbus_read_word_swapped(*client,
+                                                 chan->type == IIO_TEMP ?
+                                                 SI7020CMD_TEMP_HOLD :
+                                                 SI7020CMD_RH_HOLD);
                if (ret < 0)
                        return ret;
                *val = ret >> 2;
index 32f79624dd28565d3846384f24049e435aef83e7..9909022dc6c3eebd4c52ef3e7dca5221dc8b6038 100644 (file)
@@ -2798,7 +2798,6 @@ static struct scsi_host_template srp_template = {
        .cmd_per_lun                    = SRP_DEFAULT_CMD_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = srp_host_attrs,
-       .use_blk_tags                   = 1,
        .track_queue_depth              = 1,
 };
 
@@ -3229,10 +3228,6 @@ static ssize_t srp_create_target(struct device *dev,
        if (ret)
                goto out;
 
-       ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
-       if (ret)
-               goto out;
-
        target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
 
        if (!srp_conn_unique(target->srp_host, target)) {
index 47c4022fda7680e3107710bb703e83fa61affc15..2e2fe818ca9f1acc42d74c8f4d0e0cfbaf810172 100644 (file)
@@ -43,9 +43,7 @@
 #include <linux/atomic.h>
 #include <scsi/scsi_proto.h>
 #include <scsi/scsi_tcq.h>
-#include <target/configfs_macros.h>
 #include <target/target_core_base.h>
-#include <target/target_core_fabric_configfs.h>
 #include <target/target_core_fabric.h>
 #include "ib_srpt.h"
 
@@ -3546,20 +3544,19 @@ static void srpt_cleanup_nodeacl(struct se_node_acl *se_nacl)
        spin_unlock_irq(&sport->port_acl_lock);
 }
 
-static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t srpt_tpg_attrib_srp_max_rdma_size_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
 
        return sprintf(page, "%u\n", sport->port_attrib.srp_max_rdma_size);
 }
 
-static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t srpt_tpg_attrib_srp_max_rdma_size_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
        unsigned long val;
        int ret;
@@ -3584,22 +3581,19 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(
        return count;
 }
 
-TF_TPG_ATTRIB_ATTR(srpt, srp_max_rdma_size, S_IRUGO | S_IWUSR);
-
-static ssize_t srpt_tpg_attrib_show_srp_max_rsp_size(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t srpt_tpg_attrib_srp_max_rsp_size_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
 
        return sprintf(page, "%u\n", sport->port_attrib.srp_max_rsp_size);
 }
 
-static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t srpt_tpg_attrib_srp_max_rsp_size_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
        unsigned long val;
        int ret;
@@ -3624,22 +3618,19 @@ static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(
        return count;
 }
 
-TF_TPG_ATTRIB_ATTR(srpt, srp_max_rsp_size, S_IRUGO | S_IWUSR);
-
-static ssize_t srpt_tpg_attrib_show_srp_sq_size(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t srpt_tpg_attrib_srp_sq_size_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
 
        return sprintf(page, "%u\n", sport->port_attrib.srp_sq_size);
 }
 
-static ssize_t srpt_tpg_attrib_store_srp_sq_size(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t srpt_tpg_attrib_srp_sq_size_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
        unsigned long val;
        int ret;
@@ -3664,29 +3655,29 @@ static ssize_t srpt_tpg_attrib_store_srp_sq_size(
        return count;
 }
 
-TF_TPG_ATTRIB_ATTR(srpt, srp_sq_size, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(srpt_tpg_attrib_,  srp_max_rdma_size);
+CONFIGFS_ATTR(srpt_tpg_attrib_,  srp_max_rsp_size);
+CONFIGFS_ATTR(srpt_tpg_attrib_,  srp_sq_size);
 
 static struct configfs_attribute *srpt_tpg_attrib_attrs[] = {
-       &srpt_tpg_attrib_srp_max_rdma_size.attr,
-       &srpt_tpg_attrib_srp_max_rsp_size.attr,
-       &srpt_tpg_attrib_srp_sq_size.attr,
+       &srpt_tpg_attrib_attr_srp_max_rdma_size,
+       &srpt_tpg_attrib_attr_srp_max_rsp_size,
+       &srpt_tpg_attrib_attr_srp_sq_size,
        NULL,
 };
 
-static ssize_t srpt_tpg_show_enable(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t srpt_tpg_enable_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
 
        return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0);
 }
 
-static ssize_t srpt_tpg_store_enable(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t srpt_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);
        unsigned long tmp;
         int ret;
@@ -3709,10 +3700,10 @@ static ssize_t srpt_tpg_store_enable(
        return count;
 }
 
-TF_TPG_BASE_ATTR(srpt, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(srpt_tpg_, enable);
 
 static struct configfs_attribute *srpt_tpg_attrs[] = {
-       &srpt_tpg_enable.attr,
+       &srpt_tpg_attr_enable,
        NULL,
 };
 
@@ -3782,16 +3773,15 @@ static void srpt_drop_tport(struct se_wwn *wwn)
        pr_debug("drop_tport(%s\n", config_item_name(&sport->port_wwn.wwn_group.cg_item));
 }
 
-static ssize_t srpt_wwn_show_attr_version(struct target_fabric_configfs *tf,
-                                             char *buf)
+static ssize_t srpt_wwn_version_show(struct config_item *item, char *buf)
 {
        return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION);
 }
 
-TF_WWN_ATTR_RO(srpt, version);
+CONFIGFS_ATTR_RO(srpt_wwn_, version);
 
 static struct configfs_attribute *srpt_wwn_attrs[] = {
-       &srpt_wwn_version.attr,
+       &srpt_wwn_attr_version,
        NULL,
 };
 
index 2955f1d0ca6c4c9137f786028ca36bff706beab2..537ebb0e193a2a6f47e919c172151f37aa14b4c4 100644 (file)
@@ -1520,6 +1520,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"),
                },
        },
+       {
+               /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
+               },
+       },
 #endif
        { }
 };
index 74bb17270255439c6354f983676fdac121410c01..92c31b8f8fb489c317013f1cf77f133993fcc321 100644 (file)
@@ -164,7 +164,7 @@ static int parkbd_getport(struct parport *pp)
        return 0;
 }
 
-static struct serio * __init parkbd_allocate_serio(void)
+static struct serio *parkbd_allocate_serio(void)
 {
        struct serio *serio;
 
index 80cc69897a4331105801ff3eca9339819727e3c8..ae33da7ab51ff7f5f84464366be1c4b9f8030527 100644 (file)
@@ -939,10 +939,27 @@ config TOUCHSCREEN_TSC_SERIO
          To compile this driver as a module, choose M here: the
          module will be called tsc40.
 
+config TOUCHSCREEN_TSC200X_CORE
+       tristate
+
+config TOUCHSCREEN_TSC2004
+       tristate "TSC2004 based touchscreens"
+       depends on I2C
+       select REGMAP_I2C
+       select TOUCHSCREEN_TSC200X_CORE
+       help
+         Say Y here if you have a TSC2004 based touchscreen.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tsc2004.
+
 config TOUCHSCREEN_TSC2005
        tristate "TSC2005 based touchscreens"
        depends on SPI_MASTER
        select REGMAP_SPI
+       select TOUCHSCREEN_TSC200X_CORE
        help
          Say Y here if you have a TSC2005 based touchscreen.
 
index 17435c7e97e3bcbf421ce1135e9c64bec05f2c6a..cbaa6abb08dae6c58ea1125b0fc0baa335dbc444 100644 (file)
@@ -69,6 +69,8 @@ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)  += touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_TSC_SERIO)    += tsc40.o
+obj-$(CONFIG_TOUCHSCREEN_TSC200X_CORE) += tsc200x-core.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2004)      += tsc2004.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2005)      += tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)      += tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)      += ucb1400_ts.o
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
new file mode 100644 (file)
index 0000000..7295c19
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * TSC2004 touchscreen driver
+ *
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC 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.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include "tsc200x-core.h"
+
+static int tsc2004_cmd(struct device *dev, u8 cmd)
+{
+       u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
+       s32 data;
+       struct i2c_client *i2c = to_i2c_client(dev);
+
+       data = i2c_smbus_write_byte(i2c, tx);
+       if (data < 0) {
+               dev_err(dev, "%s: failed, command: %x i2c error: %d\n",
+                       __func__, cmd, data);
+               return data;
+       }
+
+       return 0;
+}
+
+static int tsc2004_probe(struct i2c_client *i2c,
+                        const struct i2c_device_id *id)
+
+{
+       return tsc200x_probe(&i2c->dev, i2c->irq, BUS_I2C,
+                            devm_regmap_init_i2c(i2c, &tsc200x_regmap_config),
+                            tsc2004_cmd);
+}
+
+static int tsc2004_remove(struct i2c_client *i2c)
+{
+       return tsc200x_remove(&i2c->dev);
+}
+
+static const struct i2c_device_id tsc2004_idtable[] = {
+       { "tsc2004", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
+
+#ifdef CONFIG_OF
+static const struct of_device_id tsc2004_of_match[] = {
+       { .compatible = "ti,tsc2004" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tsc2004_of_match);
+#endif
+
+static struct i2c_driver tsc2004_driver = {
+       .driver = {
+               .name   = "tsc2004",
+               .of_match_table = of_match_ptr(tsc2004_of_match),
+               .pm     = &tsc200x_pm_ops,
+       },
+       .id_table       = tsc2004_idtable,
+       .probe          = tsc2004_probe,
+       .remove         = tsc2004_remove,
+};
+module_i2c_driver(tsc2004_driver);
+
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
+MODULE_DESCRIPTION("TSC2004 Touchscreen Driver");
+MODULE_LICENSE("GPL");
index f41f23318484d1fb97a427b38e28f15c6e585f57..b9f593dfd2ef8368223e5d7d7d9ca06856afcc8d 100644 (file)
@@ -2,9 +2,10 @@
  * TSC2005 touchscreen driver
  *
  * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC Inc.
  *
- * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
- * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
+ * Based on original tsc2005.c by Lauri Leukkunen <lauri.leukkunen@nokia.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
  */
 
-#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/input.h>
-#include <linux/input/touchscreen.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/of.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/tsc2005.h>
-#include <linux/regulator/consumer.h>
 #include <linux/regmap.h>
-#include <linux/gpio/consumer.h>
-
-/*
- * The touchscreen interface operates as follows:
- *
- * 1) Pen is pressed against the touchscreen.
- * 2) TSC2005 performs AD conversion.
- * 3) After the conversion is done TSC2005 drives DAV line down.
- * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
- * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
- *    values.
- * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
- *    tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
- * 7) When the penup timer expires, there have not been touch or DAV interrupts
- *    during the last 40ms which means the pen has been lifted.
- *
- * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
- * after a configurable period (in ms) of activity. If esd_timeout is 0, the
- * watchdog is disabled.
- */
-
-/* control byte 1 */
-#define TSC2005_CMD                    0x80
-#define TSC2005_CMD_NORMAL             0x00
-#define TSC2005_CMD_STOP               0x01
-#define TSC2005_CMD_12BIT              0x04
-
-/* control byte 0 */
-#define TSC2005_REG_READ               0x01 /* R/W access */
-#define TSC2005_REG_PND0               0x02 /* Power Not Down Control */
-#define TSC2005_REG_X                  (0x0 << 3)
-#define TSC2005_REG_Y                  (0x1 << 3)
-#define TSC2005_REG_Z1                 (0x2 << 3)
-#define TSC2005_REG_Z2                 (0x3 << 3)
-#define TSC2005_REG_AUX                        (0x4 << 3)
-#define TSC2005_REG_TEMP1              (0x5 << 3)
-#define TSC2005_REG_TEMP2              (0x6 << 3)
-#define TSC2005_REG_STATUS             (0x7 << 3)
-#define TSC2005_REG_AUX_HIGH           (0x8 << 3)
-#define TSC2005_REG_AUX_LOW            (0x9 << 3)
-#define TSC2005_REG_TEMP_HIGH          (0xA << 3)
-#define TSC2005_REG_TEMP_LOW           (0xB << 3)
-#define TSC2005_REG_CFR0               (0xC << 3)
-#define TSC2005_REG_CFR1               (0xD << 3)
-#define TSC2005_REG_CFR2               (0xE << 3)
-#define TSC2005_REG_CONV_FUNC          (0xF << 3)
-
-/* configuration register 0 */
-#define TSC2005_CFR0_PRECHARGE_276US   0x0040
-#define TSC2005_CFR0_STABTIME_1MS      0x0300
-#define TSC2005_CFR0_CLOCK_1MHZ                0x1000
-#define TSC2005_CFR0_RESOLUTION12      0x2000
-#define TSC2005_CFR0_PENMODE           0x8000
-#define TSC2005_CFR0_INITVALUE         (TSC2005_CFR0_STABTIME_1MS    | \
-                                        TSC2005_CFR0_CLOCK_1MHZ      | \
-                                        TSC2005_CFR0_RESOLUTION12    | \
-                                        TSC2005_CFR0_PRECHARGE_276US | \
-                                        TSC2005_CFR0_PENMODE)
-
-/* bits common to both read and write of configuration register 0 */
-#define        TSC2005_CFR0_RW_MASK            0x3fff
-
-/* configuration register 1 */
-#define TSC2005_CFR1_BATCHDELAY_4MS    0x0003
-#define TSC2005_CFR1_INITVALUE         TSC2005_CFR1_BATCHDELAY_4MS
-
-/* configuration register 2 */
-#define TSC2005_CFR2_MAVE_Z            0x0004
-#define TSC2005_CFR2_MAVE_Y            0x0008
-#define TSC2005_CFR2_MAVE_X            0x0010
-#define TSC2005_CFR2_AVG_7             0x0800
-#define TSC2005_CFR2_MEDIUM_15         0x3000
-#define TSC2005_CFR2_INITVALUE         (TSC2005_CFR2_MAVE_X    | \
-                                        TSC2005_CFR2_MAVE_Y    | \
-                                        TSC2005_CFR2_MAVE_Z    | \
-                                        TSC2005_CFR2_MEDIUM_15 | \
-                                        TSC2005_CFR2_AVG_7)
-
-#define MAX_12BIT                      0xfff
-#define TSC2005_DEF_X_FUZZ             4
-#define TSC2005_DEF_Y_FUZZ             8
-#define TSC2005_DEF_P_FUZZ             2
-#define TSC2005_DEF_RESISTOR           280
-
-#define TSC2005_SPI_MAX_SPEED_HZ       10000000
-#define TSC2005_PENUP_TIME_MS          40
-
-static const struct regmap_range tsc2005_writable_ranges[] = {
-       regmap_reg_range(TSC2005_REG_AUX_HIGH, TSC2005_REG_CFR2),
-};
-
-static const struct regmap_access_table tsc2005_writable_table = {
-       .yes_ranges = tsc2005_writable_ranges,
-       .n_yes_ranges = ARRAY_SIZE(tsc2005_writable_ranges),
-};
-
-static struct regmap_config tsc2005_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 16,
-       .reg_stride = 0x08,
-       .max_register = 0x78,
-       .read_flag_mask = TSC2005_REG_READ,
-       .write_flag_mask = TSC2005_REG_PND0,
-       .wr_table = &tsc2005_writable_table,
-       .use_single_rw = true,
-};
-
-struct tsc2005_data {
-       u16 x;
-       u16 y;
-       u16 z1;
-       u16 z2;
-} __packed;
-#define TSC2005_DATA_REGS 4
-
-struct tsc2005 {
-       struct spi_device       *spi;
-       struct regmap           *regmap;
-
-       struct input_dev        *idev;
-       char                    phys[32];
-
-       struct mutex            mutex;
-
-       /* raw copy of previous x,y,z */
-       int                     in_x;
-       int                     in_y;
-       int                     in_z1;
-       int                     in_z2;
-
-       spinlock_t              lock;
-       struct timer_list       penup_timer;
+#include "tsc200x-core.h"
 
-       unsigned int            esd_timeout;
-       struct delayed_work     esd_work;
-       unsigned long           last_valid_interrupt;
-
-       unsigned int            x_plate_ohm;
-
-       bool                    opened;
-       bool                    suspended;
-
-       bool                    pen_down;
-
-       struct regulator        *vio;
-
-       struct gpio_desc        *reset_gpio;
-       void                    (*set_reset)(bool enable);
-};
-
-static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
+static int tsc2005_cmd(struct device *dev, u8 cmd)
 {
-       u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
+       u8 tx = TSC200X_CMD | TSC200X_CMD_12BIT | cmd;
        struct spi_transfer xfer = {
-               .tx_buf         = &tx,
-               .len            = 1,
-               .bits_per_word  = 8,
+               .tx_buf         = &tx,
+               .len            = 1,
+               .bits_per_word  = 8,
        };
        struct spi_message msg;
+       struct spi_device *spi = to_spi_device(dev);
        int error;
 
        spi_message_init(&msg);
        spi_message_add_tail(&xfer, &msg);
 
-       error = spi_sync(ts->spi, &msg);
+       error = spi_sync(spi, &msg);
        if (error) {
-               dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
+               dev_err(dev, "%s: failed, command: %x, spi error: %d\n",
                        __func__, cmd, error);
                return error;
        }
@@ -208,382 +49,10 @@ static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
        return 0;
 }
 
-static void tsc2005_update_pen_state(struct tsc2005 *ts,
-                                    int x, int y, int pressure)
-{
-       if (pressure) {
-               input_report_abs(ts->idev, ABS_X, x);
-               input_report_abs(ts->idev, ABS_Y, y);
-               input_report_abs(ts->idev, ABS_PRESSURE, pressure);
-               if (!ts->pen_down) {
-                       input_report_key(ts->idev, BTN_TOUCH, !!pressure);
-                       ts->pen_down = true;
-               }
-       } else {
-               input_report_abs(ts->idev, ABS_PRESSURE, 0);
-               if (ts->pen_down) {
-                       input_report_key(ts->idev, BTN_TOUCH, 0);
-                       ts->pen_down = false;
-               }
-       }
-       input_sync(ts->idev);
-       dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
-               pressure);
-}
-
-static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
-{
-       struct tsc2005 *ts = _ts;
-       unsigned long flags;
-       unsigned int pressure;
-       struct tsc2005_data tsdata;
-       int error;
-
-       /* read the coordinates */
-       error = regmap_bulk_read(ts->regmap, TSC2005_REG_X, &tsdata,
-                                TSC2005_DATA_REGS);
-       if (unlikely(error))
-               goto out;
-
-       /* validate position */
-       if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
-               goto out;
-
-       /* Skip reading if the pressure components are out of range */
-       if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
-               goto out;
-       if (unlikely(tsdata.z1 >= tsdata.z2))
-               goto out;
-
-       /*
-       * Skip point if this is a pen down with the exact same values as
-       * the value before pen-up - that implies SPI fed us stale data
-       */
-       if (!ts->pen_down &&
-           ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
-           ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
-               goto out;
-       }
-
-       /*
-        * At this point we are happy we have a valid and useful reading.
-        * Remember it for later comparisons. We may now begin downsampling.
-        */
-       ts->in_x = tsdata.x;
-       ts->in_y = tsdata.y;
-       ts->in_z1 = tsdata.z1;
-       ts->in_z2 = tsdata.z2;
-
-       /* Compute touch pressure resistance using equation #1 */
-       pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
-       pressure = pressure * ts->x_plate_ohm / 4096;
-       if (unlikely(pressure > MAX_12BIT))
-               goto out;
-
-       spin_lock_irqsave(&ts->lock, flags);
-
-       tsc2005_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
-       mod_timer(&ts->penup_timer,
-                 jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
-
-       spin_unlock_irqrestore(&ts->lock, flags);
-
-       ts->last_valid_interrupt = jiffies;
-out:
-       return IRQ_HANDLED;
-}
-
-static void tsc2005_penup_timer(unsigned long data)
-{
-       struct tsc2005 *ts = (struct tsc2005 *)data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ts->lock, flags);
-       tsc2005_update_pen_state(ts, 0, 0, 0);
-       spin_unlock_irqrestore(&ts->lock, flags);
-}
-
-static void tsc2005_start_scan(struct tsc2005 *ts)
-{
-       regmap_write(ts->regmap, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
-       regmap_write(ts->regmap, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
-       regmap_write(ts->regmap, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
-       tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
-}
-
-static void tsc2005_stop_scan(struct tsc2005 *ts)
-{
-       tsc2005_cmd(ts, TSC2005_CMD_STOP);
-}
-
-static void tsc2005_set_reset(struct tsc2005 *ts, bool enable)
-{
-       if (ts->reset_gpio)
-               gpiod_set_value_cansleep(ts->reset_gpio, enable);
-       else if (ts->set_reset)
-               ts->set_reset(enable);
-}
-
-/* must be called with ts->mutex held */
-static void __tsc2005_disable(struct tsc2005 *ts)
-{
-       tsc2005_stop_scan(ts);
-
-       disable_irq(ts->spi->irq);
-       del_timer_sync(&ts->penup_timer);
-
-       cancel_delayed_work_sync(&ts->esd_work);
-
-       enable_irq(ts->spi->irq);
-}
-
-/* must be called with ts->mutex held */
-static void __tsc2005_enable(struct tsc2005 *ts)
-{
-       tsc2005_start_scan(ts);
-
-       if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
-               ts->last_valid_interrupt = jiffies;
-               schedule_delayed_work(&ts->esd_work,
-                               round_jiffies_relative(
-                                       msecs_to_jiffies(ts->esd_timeout)));
-       }
-
-}
-
-static ssize_t tsc2005_selftest_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf)
-{
-       struct tsc2005 *ts = dev_get_drvdata(dev);
-       unsigned int temp_high;
-       unsigned int temp_high_orig;
-       unsigned int temp_high_test;
-       bool success = true;
-       int error;
-
-       mutex_lock(&ts->mutex);
-
-       /*
-        * Test TSC2005 communications via temp high register.
-        */
-       __tsc2005_disable(ts);
-
-       error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
-       if (error) {
-               dev_warn(dev, "selftest failed: read error %d\n", error);
-               success = false;
-               goto out;
-       }
-
-       temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
-
-       error = regmap_write(ts->regmap, TSC2005_REG_TEMP_HIGH, temp_high_test);
-       if (error) {
-               dev_warn(dev, "selftest failed: write error %d\n", error);
-               success = false;
-               goto out;
-       }
-
-       error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
-       if (error) {
-               dev_warn(dev, "selftest failed: read error %d after write\n",
-                        error);
-               success = false;
-               goto out;
-       }
-
-       if (temp_high != temp_high_test) {
-               dev_warn(dev, "selftest failed: %d != %d\n",
-                        temp_high, temp_high_test);
-               success = false;
-       }
-
-       /* hardware reset */
-       tsc2005_set_reset(ts, false);
-       usleep_range(100, 500); /* only 10us required */
-       tsc2005_set_reset(ts, true);
-
-       if (!success)
-               goto out;
-
-       /* test that the reset really happened */
-       error = regmap_read(ts->regmap, TSC2005_REG_TEMP_HIGH, &temp_high);
-       if (error) {
-               dev_warn(dev, "selftest failed: read error %d after reset\n",
-                        error);
-               success = false;
-               goto out;
-       }
-
-       if (temp_high != temp_high_orig) {
-               dev_warn(dev, "selftest failed after reset: %d != %d\n",
-                        temp_high, temp_high_orig);
-               success = false;
-       }
-
-out:
-       __tsc2005_enable(ts);
-       mutex_unlock(&ts->mutex);
-
-       return sprintf(buf, "%d\n", success);
-}
-
-static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
-
-static struct attribute *tsc2005_attrs[] = {
-       &dev_attr_selftest.attr,
-       NULL
-};
-
-static umode_t tsc2005_attr_is_visible(struct kobject *kobj,
-                                     struct attribute *attr, int n)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct tsc2005 *ts = dev_get_drvdata(dev);
-       umode_t mode = attr->mode;
-
-       if (attr == &dev_attr_selftest.attr) {
-               if (!ts->set_reset && !ts->reset_gpio)
-                       mode = 0;
-       }
-
-       return mode;
-}
-
-static const struct attribute_group tsc2005_attr_group = {
-       .is_visible     = tsc2005_attr_is_visible,
-       .attrs          = tsc2005_attrs,
-};
-
-static void tsc2005_esd_work(struct work_struct *work)
-{
-       struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
-       int error;
-       unsigned int r;
-
-       if (!mutex_trylock(&ts->mutex)) {
-               /*
-                * If the mutex is taken, it means that disable or enable is in
-                * progress. In that case just reschedule the work. If the work
-                * is not needed, it will be canceled by disable.
-                */
-               goto reschedule;
-       }
-
-       if (time_is_after_jiffies(ts->last_valid_interrupt +
-                                 msecs_to_jiffies(ts->esd_timeout)))
-               goto out;
-
-       /* We should be able to read register without disabling interrupts. */
-       error = regmap_read(ts->regmap, TSC2005_REG_CFR0, &r);
-       if (!error &&
-           !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
-               goto out;
-       }
-
-       /*
-        * If we could not read our known value from configuration register 0
-        * then we should reset the controller as if from power-up and start
-        * scanning again.
-        */
-       dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
-
-       disable_irq(ts->spi->irq);
-       del_timer_sync(&ts->penup_timer);
-
-       tsc2005_update_pen_state(ts, 0, 0, 0);
-
-       tsc2005_set_reset(ts, false);
-       usleep_range(100, 500); /* only 10us required */
-       tsc2005_set_reset(ts, true);
-
-       enable_irq(ts->spi->irq);
-       tsc2005_start_scan(ts);
-
-out:
-       mutex_unlock(&ts->mutex);
-reschedule:
-       /* re-arm the watchdog */
-       schedule_delayed_work(&ts->esd_work,
-                             round_jiffies_relative(
-                                       msecs_to_jiffies(ts->esd_timeout)));
-}
-
-static int tsc2005_open(struct input_dev *input)
-{
-       struct tsc2005 *ts = input_get_drvdata(input);
-
-       mutex_lock(&ts->mutex);
-
-       if (!ts->suspended)
-               __tsc2005_enable(ts);
-
-       ts->opened = true;
-
-       mutex_unlock(&ts->mutex);
-
-       return 0;
-}
-
-static void tsc2005_close(struct input_dev *input)
-{
-       struct tsc2005 *ts = input_get_drvdata(input);
-
-       mutex_lock(&ts->mutex);
-
-       if (!ts->suspended)
-               __tsc2005_disable(ts);
-
-       ts->opened = false;
-
-       mutex_unlock(&ts->mutex);
-}
-
 static int tsc2005_probe(struct spi_device *spi)
 {
-       const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev);
-       struct device_node *np = spi->dev.of_node;
-
-       struct tsc2005 *ts;
-       struct input_dev *input_dev;
-       unsigned int max_x = MAX_12BIT;
-       unsigned int max_y = MAX_12BIT;
-       unsigned int max_p = MAX_12BIT;
-       unsigned int fudge_x = TSC2005_DEF_X_FUZZ;
-       unsigned int fudge_y = TSC2005_DEF_Y_FUZZ;
-       unsigned int fudge_p = TSC2005_DEF_P_FUZZ;
-       unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR;
-       unsigned int esd_timeout;
        int error;
 
-       if (!np && !pdata) {
-               dev_err(&spi->dev, "no platform data\n");
-               return -ENODEV;
-       }
-
-       if (spi->irq <= 0) {
-               dev_err(&spi->dev, "no irq\n");
-               return -ENODEV;
-       }
-
-       if (pdata) {
-               fudge_x = pdata->ts_x_fudge;
-               fudge_y = pdata->ts_y_fudge;
-               fudge_p = pdata->ts_pressure_fudge;
-               max_x   = pdata->ts_x_max;
-               max_y   = pdata->ts_y_max;
-               max_p   = pdata->ts_pressure_max;
-               x_plate_ohm = pdata->ts_x_plate_ohm;
-               esd_timeout = pdata->esd_timeout_ms;
-       } else {
-               x_plate_ohm = TSC2005_DEF_RESISTOR;
-               of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
-               esd_timeout = 0;
-               of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
-                                                               &esd_timeout);
-       }
-
        spi->mode = SPI_MODE_0;
        spi->bits_per_word = 8;
        if (!spi->max_speed_hz)
@@ -593,174 +62,27 @@ static int tsc2005_probe(struct spi_device *spi)
        if (error)
                return error;
 
-       ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL);
-       if (!ts)
-               return -ENOMEM;
-
-       input_dev = devm_input_allocate_device(&spi->dev);
-       if (!input_dev)
-               return -ENOMEM;
-
-       ts->spi = spi;
-       ts->idev = input_dev;
-
-       ts->regmap = devm_regmap_init_spi(spi, &tsc2005_regmap_config);
-       if (IS_ERR(ts->regmap))
-               return PTR_ERR(ts->regmap);
-
-       ts->x_plate_ohm = x_plate_ohm;
-       ts->esd_timeout = esd_timeout;
-
-       ts->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
-                                                GPIOD_OUT_HIGH);
-       if (IS_ERR(ts->reset_gpio)) {
-               error = PTR_ERR(ts->reset_gpio);
-               dev_err(&spi->dev, "error acquiring reset gpio: %d\n", error);
-               return error;
-       }
-
-       ts->vio = devm_regulator_get_optional(&spi->dev, "vio");
-       if (IS_ERR(ts->vio)) {
-               error = PTR_ERR(ts->vio);
-               dev_err(&spi->dev, "vio regulator missing (%d)", error);
-               return error;
-       }
-
-       if (!ts->reset_gpio && pdata)
-               ts->set_reset = pdata->set_reset;
-
-       mutex_init(&ts->mutex);
-
-       spin_lock_init(&ts->lock);
-       setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
-
-       INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
-
-       snprintf(ts->phys, sizeof(ts->phys),
-                "%s/input-ts", dev_name(&spi->dev));
-
-       input_dev->name = "TSC2005 touchscreen";
-       input_dev->phys = ts->phys;
-       input_dev->id.bustype = BUS_SPI;
-       input_dev->dev.parent = &spi->dev;
-       input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
-       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-       input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
-
-       if (np)
-               touchscreen_parse_properties(input_dev, false);
-
-       input_dev->open = tsc2005_open;
-       input_dev->close = tsc2005_close;
-
-       input_set_drvdata(input_dev, ts);
-
-       /* Ensure the touchscreen is off */
-       tsc2005_stop_scan(ts);
-
-       error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
-                                         tsc2005_irq_thread,
-                                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-                                         "tsc2005", ts);
-       if (error) {
-               dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
-               return error;
-       }
-
-       /* enable regulator for DT */
-       if (ts->vio) {
-               error = regulator_enable(ts->vio);
-               if (error)
-                       return error;
-       }
-
-       dev_set_drvdata(&spi->dev, ts);
-       error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
-       if (error) {
-               dev_err(&spi->dev,
-                       "Failed to create sysfs attributes, err: %d\n", error);
-               goto disable_regulator;
-       }
-
-       error = input_register_device(ts->idev);
-       if (error) {
-               dev_err(&spi->dev,
-                       "Failed to register input device, err: %d\n", error);
-               goto err_remove_sysfs;
-       }
-
-       irq_set_irq_wake(spi->irq, 1);
-       return 0;
-
-err_remove_sysfs:
-       sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
-disable_regulator:
-       if (ts->vio)
-               regulator_disable(ts->vio);
-       return error;
+       return tsc200x_probe(&spi->dev, spi->irq, BUS_SPI,
+                            devm_regmap_init_spi(spi, &tsc200x_regmap_config),
+                            tsc2005_cmd);
 }
 
 static int tsc2005_remove(struct spi_device *spi)
 {
-       struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
-
-       sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
-
-       if (ts->vio)
-               regulator_disable(ts->vio);
-
-       return 0;
-}
-
-static int __maybe_unused tsc2005_suspend(struct device *dev)
-{
-       struct tsc2005 *ts = dev_get_drvdata(dev);
-
-       mutex_lock(&ts->mutex);
-
-       if (!ts->suspended && ts->opened)
-               __tsc2005_disable(ts);
-
-       ts->suspended = true;
-
-       mutex_unlock(&ts->mutex);
-
-       return 0;
-}
-
-static int __maybe_unused tsc2005_resume(struct device *dev)
-{
-       struct tsc2005 *ts = dev_get_drvdata(dev);
-
-       mutex_lock(&ts->mutex);
-
-       if (ts->suspended && ts->opened)
-               __tsc2005_enable(ts);
-
-       ts->suspended = false;
-
-       mutex_unlock(&ts->mutex);
-
-       return 0;
+       return tsc200x_remove(&spi->dev);
 }
 
-static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
-
 static struct spi_driver tsc2005_driver = {
        .driver = {
                .name   = "tsc2005",
-               .pm     = &tsc2005_pm_ops,
+               .pm     = &tsc200x_pm_ops,
        },
        .probe  = tsc2005_probe,
        .remove = tsc2005_remove,
 };
-
 module_spi_driver(tsc2005_driver);
 
-MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_AUTHOR("Michael Welling <mwelling@ieee.org>");
 MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("spi:tsc2005");
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
new file mode 100644 (file)
index 0000000..15240c1
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ * TSC2004/TSC2005 touchscreen driver core
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2015 QWERTY Embedded Design
+ * Copyright (C) 2015 EMAC Inc.
+ *
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/spi/tsc2005.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regmap.h>
+#include <linux/gpio/consumer.h>
+#include "tsc200x-core.h"
+
+/*
+ * The touchscreen interface operates as follows:
+ *
+ * 1) Pen is pressed against the touchscreen.
+ * 2) TSC200X performs AD conversion.
+ * 3) After the conversion is done TSC200X drives DAV line down.
+ * 4) GPIO IRQ is received and tsc200x_irq_thread() is scheduled.
+ * 5) tsc200x_irq_thread() queues up a transfer to fetch the x, y, z1, z2
+ *    values.
+ * 6) tsc200x_irq_thread() reports coordinates to input layer and sets up
+ *    tsc200x_penup_timer() to be called after TSC200X_PENUP_TIME_MS (40ms).
+ * 7) When the penup timer expires, there have not been touch or DAV interrupts
+ *    during the last 40ms which means the pen has been lifted.
+ *
+ * ESD recovery via a hardware reset is done if the TSC200X doesn't respond
+ * after a configurable period (in ms) of activity. If esd_timeout is 0, the
+ * watchdog is disabled.
+ */
+
+static const struct regmap_range tsc200x_writable_ranges[] = {
+       regmap_reg_range(TSC200X_REG_AUX_HIGH, TSC200X_REG_CFR2),
+};
+
+static const struct regmap_access_table tsc200x_writable_table = {
+       .yes_ranges = tsc200x_writable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(tsc200x_writable_ranges),
+};
+
+const struct regmap_config tsc200x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 16,
+       .reg_stride = 0x08,
+       .max_register = 0x78,
+       .read_flag_mask = TSC200X_REG_READ,
+       .write_flag_mask = TSC200X_REG_PND0,
+       .wr_table = &tsc200x_writable_table,
+       .use_single_rw = true,
+};
+EXPORT_SYMBOL_GPL(tsc200x_regmap_config);
+
+struct tsc200x_data {
+       u16 x;
+       u16 y;
+       u16 z1;
+       u16 z2;
+} __packed;
+#define TSC200X_DATA_REGS 4
+
+struct tsc200x {
+       struct device           *dev;
+       struct regmap           *regmap;
+       __u16                   bustype;
+
+       struct input_dev        *idev;
+       char                    phys[32];
+
+       struct mutex            mutex;
+
+       /* raw copy of previous x,y,z */
+       int                     in_x;
+       int                     in_y;
+       int                     in_z1;
+       int                     in_z2;
+
+       spinlock_t              lock;
+       struct timer_list       penup_timer;
+
+       unsigned int            esd_timeout;
+       struct delayed_work     esd_work;
+       unsigned long           last_valid_interrupt;
+
+       unsigned int            x_plate_ohm;
+
+       bool                    opened;
+       bool                    suspended;
+
+       bool                    pen_down;
+
+       struct regulator        *vio;
+
+       struct gpio_desc        *reset_gpio;
+       void                    (*set_reset)(bool enable);
+       int                     (*tsc200x_cmd)(struct device *dev, u8 cmd);
+       int                     irq;
+};
+
+static void tsc200x_update_pen_state(struct tsc200x *ts,
+                                    int x, int y, int pressure)
+{
+       if (pressure) {
+               input_report_abs(ts->idev, ABS_X, x);
+               input_report_abs(ts->idev, ABS_Y, y);
+               input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+               if (!ts->pen_down) {
+                       input_report_key(ts->idev, BTN_TOUCH, !!pressure);
+                       ts->pen_down = true;
+               }
+       } else {
+               input_report_abs(ts->idev, ABS_PRESSURE, 0);
+               if (ts->pen_down) {
+                       input_report_key(ts->idev, BTN_TOUCH, 0);
+                       ts->pen_down = false;
+               }
+       }
+       input_sync(ts->idev);
+       dev_dbg(ts->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
+               pressure);
+}
+
+static irqreturn_t tsc200x_irq_thread(int irq, void *_ts)
+{
+       struct tsc200x *ts = _ts;
+       unsigned long flags;
+       unsigned int pressure;
+       struct tsc200x_data tsdata;
+       int error;
+
+       /* read the coordinates */
+       error = regmap_bulk_read(ts->regmap, TSC200X_REG_X, &tsdata,
+                                TSC200X_DATA_REGS);
+       if (unlikely(error))
+               goto out;
+
+       /* validate position */
+       if (unlikely(tsdata.x > MAX_12BIT || tsdata.y > MAX_12BIT))
+               goto out;
+
+       /* Skip reading if the pressure components are out of range */
+       if (unlikely(tsdata.z1 == 0 || tsdata.z2 > MAX_12BIT))
+               goto out;
+       if (unlikely(tsdata.z1 >= tsdata.z2))
+               goto out;
+
+       /*
+       * Skip point if this is a pen down with the exact same values as
+       * the value before pen-up - that implies SPI fed us stale data
+       */
+       if (!ts->pen_down &&
+           ts->in_x == tsdata.x && ts->in_y == tsdata.y &&
+           ts->in_z1 == tsdata.z1 && ts->in_z2 == tsdata.z2) {
+               goto out;
+       }
+
+       /*
+        * At this point we are happy we have a valid and useful reading.
+        * Remember it for later comparisons. We may now begin downsampling.
+        */
+       ts->in_x = tsdata.x;
+       ts->in_y = tsdata.y;
+       ts->in_z1 = tsdata.z1;
+       ts->in_z2 = tsdata.z2;
+
+       /* Compute touch pressure resistance using equation #1 */
+       pressure = tsdata.x * (tsdata.z2 - tsdata.z1) / tsdata.z1;
+       pressure = pressure * ts->x_plate_ohm / 4096;
+       if (unlikely(pressure > MAX_12BIT))
+               goto out;
+
+       spin_lock_irqsave(&ts->lock, flags);
+
+       tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure);
+       mod_timer(&ts->penup_timer,
+                 jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS));
+
+       spin_unlock_irqrestore(&ts->lock, flags);
+
+       ts->last_valid_interrupt = jiffies;
+out:
+       return IRQ_HANDLED;
+}
+
+static void tsc200x_penup_timer(unsigned long data)
+{
+       struct tsc200x *ts = (struct tsc200x *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ts->lock, flags);
+       tsc200x_update_pen_state(ts, 0, 0, 0);
+       spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void tsc200x_start_scan(struct tsc200x *ts)
+{
+       regmap_write(ts->regmap, TSC200X_REG_CFR0, TSC200X_CFR0_INITVALUE);
+       regmap_write(ts->regmap, TSC200X_REG_CFR1, TSC200X_CFR1_INITVALUE);
+       regmap_write(ts->regmap, TSC200X_REG_CFR2, TSC200X_CFR2_INITVALUE);
+       ts->tsc200x_cmd(ts->dev, TSC200X_CMD_NORMAL);
+}
+
+static void tsc200x_stop_scan(struct tsc200x *ts)
+{
+       ts->tsc200x_cmd(ts->dev, TSC200X_CMD_STOP);
+}
+
+static void tsc200x_set_reset(struct tsc200x *ts, bool enable)
+{
+       if (ts->reset_gpio)
+               gpiod_set_value_cansleep(ts->reset_gpio, enable);
+       else if (ts->set_reset)
+               ts->set_reset(enable);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc200x_disable(struct tsc200x *ts)
+{
+       tsc200x_stop_scan(ts);
+
+       disable_irq(ts->irq);
+       del_timer_sync(&ts->penup_timer);
+
+       cancel_delayed_work_sync(&ts->esd_work);
+
+       enable_irq(ts->irq);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc200x_enable(struct tsc200x *ts)
+{
+       tsc200x_start_scan(ts);
+
+       if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
+               ts->last_valid_interrupt = jiffies;
+               schedule_delayed_work(&ts->esd_work,
+                               round_jiffies_relative(
+                                       msecs_to_jiffies(ts->esd_timeout)));
+       }
+}
+
+static ssize_t tsc200x_selftest_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct tsc200x *ts = dev_get_drvdata(dev);
+       unsigned int temp_high;
+       unsigned int temp_high_orig;
+       unsigned int temp_high_test;
+       bool success = true;
+       int error;
+
+       mutex_lock(&ts->mutex);
+
+       /*
+        * Test TSC200X communications via temp high register.
+        */
+       __tsc200x_disable(ts);
+
+       error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high_orig);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d\n", error);
+               success = false;
+               goto out;
+       }
+
+       temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
+
+       error = regmap_write(ts->regmap, TSC200X_REG_TEMP_HIGH, temp_high_test);
+       if (error) {
+               dev_warn(dev, "selftest failed: write error %d\n", error);
+               success = false;
+               goto out;
+       }
+
+       error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d after write\n",
+                        error);
+               success = false;
+               goto out;
+       }
+
+       if (temp_high != temp_high_test) {
+               dev_warn(dev, "selftest failed: %d != %d\n",
+                        temp_high, temp_high_test);
+               success = false;
+       }
+
+       /* hardware reset */
+       tsc200x_set_reset(ts, false);
+       usleep_range(100, 500); /* only 10us required */
+       tsc200x_set_reset(ts, true);
+
+       if (!success)
+               goto out;
+
+       /* test that the reset really happened */
+       error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high);
+       if (error) {
+               dev_warn(dev, "selftest failed: read error %d after reset\n",
+                        error);
+               success = false;
+               goto out;
+       }
+
+       if (temp_high != temp_high_orig) {
+               dev_warn(dev, "selftest failed after reset: %d != %d\n",
+                        temp_high, temp_high_orig);
+               success = false;
+       }
+
+out:
+       __tsc200x_enable(ts);
+       mutex_unlock(&ts->mutex);
+
+       return sprintf(buf, "%d\n", success);
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, tsc200x_selftest_show, NULL);
+
+static struct attribute *tsc200x_attrs[] = {
+       &dev_attr_selftest.attr,
+       NULL
+};
+
+static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
+                                     struct attribute *attr, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct tsc200x *ts = dev_get_drvdata(dev);
+       umode_t mode = attr->mode;
+
+       if (attr == &dev_attr_selftest.attr) {
+               if (!ts->set_reset && !ts->reset_gpio)
+                       mode = 0;
+       }
+
+       return mode;
+}
+
+static const struct attribute_group tsc200x_attr_group = {
+       .is_visible     = tsc200x_attr_is_visible,
+       .attrs          = tsc200x_attrs,
+};
+
+static void tsc200x_esd_work(struct work_struct *work)
+{
+       struct tsc200x *ts = container_of(work, struct tsc200x, esd_work.work);
+       int error;
+       unsigned int r;
+
+       if (!mutex_trylock(&ts->mutex)) {
+               /*
+                * If the mutex is taken, it means that disable or enable is in
+                * progress. In that case just reschedule the work. If the work
+                * is not needed, it will be canceled by disable.
+                */
+               goto reschedule;
+       }
+
+       if (time_is_after_jiffies(ts->last_valid_interrupt +
+                                 msecs_to_jiffies(ts->esd_timeout)))
+               goto out;
+
+       /* We should be able to read register without disabling interrupts. */
+       error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r);
+       if (!error &&
+           !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) {
+               goto out;
+       }
+
+       /*
+        * If we could not read our known value from configuration register 0
+        * then we should reset the controller as if from power-up and start
+        * scanning again.
+        */
+       dev_info(ts->dev, "TSC200X not responding - resetting\n");
+
+       disable_irq(ts->irq);
+       del_timer_sync(&ts->penup_timer);
+
+       tsc200x_update_pen_state(ts, 0, 0, 0);
+
+       tsc200x_set_reset(ts, false);
+       usleep_range(100, 500); /* only 10us required */
+       tsc200x_set_reset(ts, true);
+
+       enable_irq(ts->irq);
+       tsc200x_start_scan(ts);
+
+out:
+       mutex_unlock(&ts->mutex);
+reschedule:
+       /* re-arm the watchdog */
+       schedule_delayed_work(&ts->esd_work,
+                             round_jiffies_relative(
+                                       msecs_to_jiffies(ts->esd_timeout)));
+}
+
+static int tsc200x_open(struct input_dev *input)
+{
+       struct tsc200x *ts = input_get_drvdata(input);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended)
+               __tsc200x_enable(ts);
+
+       ts->opened = true;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+
+static void tsc200x_close(struct input_dev *input)
+{
+       struct tsc200x *ts = input_get_drvdata(input);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended)
+               __tsc200x_disable(ts);
+
+       ts->opened = false;
+
+       mutex_unlock(&ts->mutex);
+}
+
+int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+                 struct regmap *regmap,
+                 int (*tsc200x_cmd)(struct device *dev, u8 cmd))
+{
+       const struct tsc2005_platform_data *pdata = dev_get_platdata(dev);
+       struct device_node *np = dev->of_node;
+
+       struct tsc200x *ts;
+       struct input_dev *input_dev;
+       unsigned int max_x = MAX_12BIT;
+       unsigned int max_y = MAX_12BIT;
+       unsigned int max_p = MAX_12BIT;
+       unsigned int fudge_x = TSC200X_DEF_X_FUZZ;
+       unsigned int fudge_y = TSC200X_DEF_Y_FUZZ;
+       unsigned int fudge_p = TSC200X_DEF_P_FUZZ;
+       unsigned int x_plate_ohm = TSC200X_DEF_RESISTOR;
+       unsigned int esd_timeout;
+       int error;
+
+       if (!np && !pdata) {
+               dev_err(dev, "no platform data\n");
+               return -ENODEV;
+       }
+
+       if (irq <= 0) {
+               dev_err(dev, "no irq\n");
+               return -ENODEV;
+       }
+
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       if (!tsc200x_cmd) {
+               dev_err(dev, "no cmd function\n");
+               return -ENODEV;
+       }
+
+       if (pdata) {
+               fudge_x = pdata->ts_x_fudge;
+               fudge_y = pdata->ts_y_fudge;
+               fudge_p = pdata->ts_pressure_fudge;
+               max_x   = pdata->ts_x_max;
+               max_y   = pdata->ts_y_max;
+               max_p   = pdata->ts_pressure_max;
+               x_plate_ohm = pdata->ts_x_plate_ohm;
+               esd_timeout = pdata->esd_timeout_ms;
+       } else {
+               x_plate_ohm = TSC200X_DEF_RESISTOR;
+               of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
+               esd_timeout = 0;
+               of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
+                                                               &esd_timeout);
+       }
+
+       ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       input_dev = devm_input_allocate_device(dev);
+       if (!input_dev)
+               return -ENOMEM;
+
+       ts->irq = irq;
+       ts->dev = dev;
+       ts->idev = input_dev;
+       ts->regmap = regmap;
+       ts->tsc200x_cmd = tsc200x_cmd;
+       ts->x_plate_ohm = x_plate_ohm;
+       ts->esd_timeout = esd_timeout;
+
+       ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(ts->reset_gpio)) {
+               error = PTR_ERR(ts->reset_gpio);
+               dev_err(dev, "error acquiring reset gpio: %d\n", error);
+               return error;
+       }
+
+       ts->vio = devm_regulator_get_optional(dev, "vio");
+       if (IS_ERR(ts->vio)) {
+               error = PTR_ERR(ts->vio);
+               dev_err(dev, "vio regulator missing (%d)", error);
+               return error;
+       }
+
+       if (!ts->reset_gpio && pdata)
+               ts->set_reset = pdata->set_reset;
+
+       mutex_init(&ts->mutex);
+
+       spin_lock_init(&ts->lock);
+       setup_timer(&ts->penup_timer, tsc200x_penup_timer, (unsigned long)ts);
+
+       INIT_DELAYED_WORK(&ts->esd_work, tsc200x_esd_work);
+
+       snprintf(ts->phys, sizeof(ts->phys),
+                "%s/input-ts", dev_name(dev));
+
+       input_dev->name = "TSC200X touchscreen";
+       input_dev->phys = ts->phys;
+       input_dev->id.bustype = bustype;
+       input_dev->dev.parent = dev;
+       input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
+
+       if (np)
+               touchscreen_parse_properties(input_dev, false);
+
+       input_dev->open = tsc200x_open;
+       input_dev->close = tsc200x_close;
+
+       input_set_drvdata(input_dev, ts);
+
+       /* Ensure the touchscreen is off */
+       tsc200x_stop_scan(ts);
+
+       error = devm_request_threaded_irq(dev, irq, NULL,
+                                         tsc200x_irq_thread,
+                                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                         "tsc200x", ts);
+       if (error) {
+               dev_err(dev, "Failed to request irq, err: %d\n", error);
+               return error;
+       }
+
+       /* enable regulator for DT */
+       if (ts->vio) {
+               error = regulator_enable(ts->vio);
+               if (error)
+                       return error;
+       }
+
+       dev_set_drvdata(dev, ts);
+       error = sysfs_create_group(&dev->kobj, &tsc200x_attr_group);
+       if (error) {
+               dev_err(dev,
+                       "Failed to create sysfs attributes, err: %d\n", error);
+               goto disable_regulator;
+       }
+
+       error = input_register_device(ts->idev);
+       if (error) {
+               dev_err(dev,
+                       "Failed to register input device, err: %d\n", error);
+               goto err_remove_sysfs;
+       }
+
+       irq_set_irq_wake(irq, 1);
+       return 0;
+
+err_remove_sysfs:
+       sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
+disable_regulator:
+       if (ts->vio)
+               regulator_disable(ts->vio);
+       return error;
+}
+EXPORT_SYMBOL_GPL(tsc200x_probe);
+
+int tsc200x_remove(struct device *dev)
+{
+       struct tsc200x *ts = dev_get_drvdata(dev);
+
+       sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
+
+       if (ts->vio)
+               regulator_disable(ts->vio);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tsc200x_remove);
+
+static int __maybe_unused tsc200x_suspend(struct device *dev)
+{
+       struct tsc200x *ts = dev_get_drvdata(dev);
+
+       mutex_lock(&ts->mutex);
+
+       if (!ts->suspended && ts->opened)
+               __tsc200x_disable(ts);
+
+       ts->suspended = true;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+
+static int __maybe_unused tsc200x_resume(struct device *dev)
+{
+       struct tsc200x *ts = dev_get_drvdata(dev);
+
+       mutex_lock(&ts->mutex);
+
+       if (ts->suspended && ts->opened)
+               __tsc200x_enable(ts);
+
+       ts->suspended = false;
+
+       mutex_unlock(&ts->mutex);
+
+       return 0;
+}
+
+SIMPLE_DEV_PM_OPS(tsc200x_pm_ops, tsc200x_suspend, tsc200x_resume);
+EXPORT_SYMBOL_GPL(tsc200x_pm_ops);
+
+MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_DESCRIPTION("TSC200x Touchscreen Driver Core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tsc200x-core.h b/drivers/input/touchscreen/tsc200x-core.h
new file mode 100644 (file)
index 0000000..7a482d1
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _TSC200X_CORE_H
+#define _TSC200X_CORE_H
+
+/* control byte 1 */
+#define TSC200X_CMD                    0x80
+#define TSC200X_CMD_NORMAL             0x00
+#define TSC200X_CMD_STOP               0x01
+#define TSC200X_CMD_12BIT              0x04
+
+/* control byte 0 */
+#define TSC200X_REG_READ               0x01 /* R/W access */
+#define TSC200X_REG_PND0               0x02 /* Power Not Down Control */
+#define TSC200X_REG_X                  (0x0 << 3)
+#define TSC200X_REG_Y                  (0x1 << 3)
+#define TSC200X_REG_Z1                 (0x2 << 3)
+#define TSC200X_REG_Z2                 (0x3 << 3)
+#define TSC200X_REG_AUX                        (0x4 << 3)
+#define TSC200X_REG_TEMP1              (0x5 << 3)
+#define TSC200X_REG_TEMP2              (0x6 << 3)
+#define TSC200X_REG_STATUS             (0x7 << 3)
+#define TSC200X_REG_AUX_HIGH           (0x8 << 3)
+#define TSC200X_REG_AUX_LOW            (0x9 << 3)
+#define TSC200X_REG_TEMP_HIGH          (0xA << 3)
+#define TSC200X_REG_TEMP_LOW           (0xB << 3)
+#define TSC200X_REG_CFR0               (0xC << 3)
+#define TSC200X_REG_CFR1               (0xD << 3)
+#define TSC200X_REG_CFR2               (0xE << 3)
+#define TSC200X_REG_CONV_FUNC          (0xF << 3)
+
+/* configuration register 0 */
+#define TSC200X_CFR0_PRECHARGE_276US   0x0040
+#define TSC200X_CFR0_STABTIME_1MS      0x0300
+#define TSC200X_CFR0_CLOCK_1MHZ                0x1000
+#define TSC200X_CFR0_RESOLUTION12      0x2000
+#define TSC200X_CFR0_PENMODE           0x8000
+#define TSC200X_CFR0_INITVALUE         (TSC200X_CFR0_STABTIME_1MS    | \
+                                        TSC200X_CFR0_CLOCK_1MHZ      | \
+                                        TSC200X_CFR0_RESOLUTION12    | \
+                                        TSC200X_CFR0_PRECHARGE_276US | \
+                                        TSC200X_CFR0_PENMODE)
+
+/* bits common to both read and write of configuration register 0 */
+#define        TSC200X_CFR0_RW_MASK            0x3fff
+
+/* configuration register 1 */
+#define TSC200X_CFR1_BATCHDELAY_4MS    0x0003
+#define TSC200X_CFR1_INITVALUE         TSC200X_CFR1_BATCHDELAY_4MS
+
+/* configuration register 2 */
+#define TSC200X_CFR2_MAVE_Z            0x0004
+#define TSC200X_CFR2_MAVE_Y            0x0008
+#define TSC200X_CFR2_MAVE_X            0x0010
+#define TSC200X_CFR2_AVG_7             0x0800
+#define TSC200X_CFR2_MEDIUM_15         0x3000
+#define TSC200X_CFR2_INITVALUE         (TSC200X_CFR2_MAVE_X    | \
+                                        TSC200X_CFR2_MAVE_Y    | \
+                                        TSC200X_CFR2_MAVE_Z    | \
+                                        TSC200X_CFR2_MEDIUM_15 | \
+                                        TSC200X_CFR2_AVG_7)
+
+#define MAX_12BIT                      0xfff
+#define TSC200X_DEF_X_FUZZ             4
+#define TSC200X_DEF_Y_FUZZ             8
+#define TSC200X_DEF_P_FUZZ             2
+#define TSC200X_DEF_RESISTOR           280
+
+#define TSC2005_SPI_MAX_SPEED_HZ       10000000
+#define TSC200X_PENUP_TIME_MS          40
+
+extern const struct regmap_config tsc200x_regmap_config;
+extern const struct dev_pm_ops tsc200x_pm_ops;
+
+int tsc200x_probe(struct device *dev, int irq, __u16 bustype,
+                 struct regmap *regmap,
+                 int (*tsc200x_cmd)(struct device *dev, u8 cmd));
+int tsc200x_remove(struct device *dev);
+
+#endif
index cbe198cb36991d3970f5a0ce4fc3596ee85eb5a7..471ee36b9c6eea6d72ad74302fadfb97c28f8a7f 100644 (file)
@@ -216,6 +216,7 @@ static int s390_iommu_update_trans(struct s390_domain *s390_domain,
        u8 *page_addr = (u8 *) (pa & PAGE_MASK);
        dma_addr_t start_dma_addr = dma_addr;
        unsigned long irq_flags, nr_pages, i;
+       unsigned long *entry;
        int rc = 0;
 
        if (dma_addr < s390_domain->domain.geometry.aperture_start ||
@@ -228,8 +229,12 @@ static int s390_iommu_update_trans(struct s390_domain *s390_domain,
 
        spin_lock_irqsave(&s390_domain->dma_table_lock, irq_flags);
        for (i = 0; i < nr_pages; i++) {
-               dma_update_cpu_trans(s390_domain->dma_table, page_addr,
-                                    dma_addr, flags);
+               entry = dma_walk_cpu_trans(s390_domain->dma_table, dma_addr);
+               if (!entry) {
+                       rc = -ENOMEM;
+                       goto undo_cpu_trans;
+               }
+               dma_update_cpu_trans(entry, page_addr, flags);
                page_addr += PAGE_SIZE;
                dma_addr += PAGE_SIZE;
        }
@@ -242,6 +247,20 @@ static int s390_iommu_update_trans(struct s390_domain *s390_domain,
                        break;
        }
        spin_unlock(&s390_domain->list_lock);
+
+undo_cpu_trans:
+       if (rc && ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)) {
+               flags = ZPCI_PTE_INVALID;
+               while (i-- > 0) {
+                       page_addr -= PAGE_SIZE;
+                       dma_addr -= PAGE_SIZE;
+                       entry = dma_walk_cpu_trans(s390_domain->dma_table,
+                                                  dma_addr);
+                       if (!entry)
+                               break;
+                       dma_update_cpu_trans(entry, page_addr, flags);
+               }
+       }
        spin_unlock_irqrestore(&s390_domain->dma_table_lock, irq_flags);
 
        return rc;
index 44a077f3a4a2627c03953d9650a66e7607dd91e2..f174ce0ca36115dc36feec5f047af7bf402e180a 100644 (file)
@@ -84,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs,
                writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
 
        /*
-        * Disable all interrupts.  Leave the PPI and SGIs alone
-        * as they are enabled by redistributor registers.
+        * Deactivate and disable all SPIs. Leave the PPI and SGIs
+        * alone as they are in the redistributor registers on GICv3.
         */
-       for (i = 32; i < gic_irqs; i += 32)
+       for (i = 32; i < gic_irqs; i += 32) {
                writel_relaxed(GICD_INT_EN_CLR_X32,
-                                       base + GIC_DIST_ENABLE_CLEAR + i / 8);
+                              base + GIC_DIST_ACTIVE_CLEAR + i / 8);
+               writel_relaxed(GICD_INT_EN_CLR_X32,
+                              base + GIC_DIST_ENABLE_CLEAR + i / 8);
+       }
 
        if (sync_access)
                sync_access();
@@ -102,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
        /*
         * Deal with the banked PPI and SGI interrupts - disable all
         * PPI interrupts, ensure all SGI interrupts are enabled.
+        * Make sure everything is deactivated.
         */
+       writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
        writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
        writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
 
index 515c823c1c95cee63b46c18bed35bb70260ae9a9..abf2ffaed392270c97d14c7fdc2ab247e63a58e1 100644 (file)
@@ -73,9 +73,11 @@ struct gic_chip_data {
        union gic_base cpu_base;
 #ifdef CONFIG_CPU_PM
        u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
+       u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
        u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
        u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
        u32 __percpu *saved_ppi_enable;
+       u32 __percpu *saved_ppi_active;
        u32 __percpu *saved_ppi_conf;
 #endif
        struct irq_domain *domain;
@@ -566,6 +568,10 @@ static void gic_dist_save(unsigned int gic_nr)
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
                gic_data[gic_nr].saved_spi_enable[i] =
                        readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+
+       for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+               gic_data[gic_nr].saved_spi_active[i] =
+                       readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
 }
 
 /*
@@ -604,9 +610,19 @@ static void gic_dist_restore(unsigned int gic_nr)
                writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
                        dist_base + GIC_DIST_TARGET + i * 4);
 
-       for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
+       for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
+               writel_relaxed(GICD_INT_EN_CLR_X32,
+                       dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
                writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
                        dist_base + GIC_DIST_ENABLE_SET + i * 4);
+       }
+
+       for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
+               writel_relaxed(GICD_INT_EN_CLR_X32,
+                       dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
+               writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
+                       dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+       }
 
        writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
 }
@@ -631,6 +647,10 @@ static void gic_cpu_save(unsigned int gic_nr)
        for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
                ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
 
+       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+       for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+               ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+
        ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
        for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
                ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
@@ -654,8 +674,18 @@ static void gic_cpu_restore(unsigned int gic_nr)
                return;
 
        ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
-       for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
+       for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
+               writel_relaxed(GICD_INT_EN_CLR_X32,
+                              dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
                writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+       }
+
+       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+       for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
+               writel_relaxed(GICD_INT_EN_CLR_X32,
+                              dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
+               writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+       }
 
        ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
        for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
@@ -710,6 +740,10 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
                sizeof(u32));
        BUG_ON(!gic->saved_ppi_enable);
 
+       gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
+               sizeof(u32));
+       BUG_ON(!gic->saved_ppi_active);
+
        gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
                sizeof(u32));
        BUG_ON(!gic->saved_ppi_conf);
index aeaa061f0dbfd3694d8a9f890822eba266e2e4e0..9e17ef27a183d6f62a6f2860ee416674a314465c 100644 (file)
@@ -29,6 +29,7 @@ struct gic_pcpu_mask {
        DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
 };
 
+static unsigned long __gic_base_addr;
 static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
@@ -301,6 +302,17 @@ int gic_get_c0_fdc_int(void)
                                  GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
 }
 
+int gic_get_usm_range(struct resource *gic_usm_res)
+{
+       if (!gic_present)
+               return -1;
+
+       gic_usm_res->start = __gic_base_addr + USM_VISIBLE_SECTION_OFS;
+       gic_usm_res->end = gic_usm_res->start + (USM_VISIBLE_SECTION_SIZE - 1);
+
+       return 0;
+}
+
 static void gic_handle_shared_int(bool chained)
 {
        unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
@@ -798,6 +810,8 @@ static void __init __gic_init(unsigned long gic_base_addr,
 {
        unsigned int gicconfig;
 
+       __gic_base_addr = gic_base_addr;
+
        gic_base = ioremap_nocache(gic_base_addr, gic_addrspace_size);
 
        gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
index f659e605a4067bed3489723470e32cc9ae02b791..5178645ac42bcb85ddd7130ee81eb07fa45c2818 100644 (file)
@@ -160,11 +160,6 @@ int nvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk)
 }
 EXPORT_SYMBOL(nvm_erase_blk);
 
-static void nvm_core_free(struct nvm_dev *dev)
-{
-       kfree(dev);
-}
-
 static int nvm_core_init(struct nvm_dev *dev)
 {
        struct nvm_id *id = &dev->identity;
@@ -179,12 +174,21 @@ static int nvm_core_init(struct nvm_dev *dev)
        dev->sec_size = grp->csecs;
        dev->oob_size = grp->sos;
        dev->sec_per_pg = grp->fpg_sz / grp->csecs;
-       dev->addr_mode = id->ppat;
-       dev->addr_format = id->ppaf;
+       memcpy(&dev->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
 
        dev->plane_mode = NVM_PLANE_SINGLE;
        dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size;
 
+       if (grp->mtype != 0) {
+               pr_err("nvm: memory type not supported\n");
+               return -EINVAL;
+       }
+
+       if (grp->fmtype != 0 && grp->fmtype != 1) {
+               pr_err("nvm: flash type not supported\n");
+               return -EINVAL;
+       }
+
        if (grp->mpos & 0x020202)
                dev->plane_mode = NVM_PLANE_DOUBLE;
        if (grp->mpos & 0x040404)
@@ -213,21 +217,18 @@ static void nvm_free(struct nvm_dev *dev)
 
        if (dev->mt)
                dev->mt->unregister_mgr(dev);
-
-       nvm_core_free(dev);
 }
 
 static int nvm_init(struct nvm_dev *dev)
 {
        struct nvmm_type *mt;
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (!dev->q || !dev->ops)
-               return -EINVAL;
+               return ret;
 
        if (dev->ops->identity(dev->q, &dev->identity)) {
                pr_err("nvm: device could not be identified\n");
-               ret = -EINVAL;
                goto err;
        }
 
@@ -273,7 +274,6 @@ static int nvm_init(struct nvm_dev *dev)
                        dev->nr_chnls);
        return 0;
 err:
-       nvm_free(dev);
        pr_err("nvm: failed to initialize nvm\n");
        return ret;
 }
@@ -308,22 +308,24 @@ int nvm_register(struct request_queue *q, char *disk_name,
        if (ret)
                goto err_init;
 
-       down_write(&nvm_lock);
-       list_add(&dev->devices, &nvm_devices);
-       up_write(&nvm_lock);
-
        if (dev->ops->max_phys_sect > 1) {
                dev->ppalist_pool = dev->ops->create_dma_pool(dev->q,
                                                                "ppalist");
                if (!dev->ppalist_pool) {
                        pr_err("nvm: could not create ppa pool\n");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_init;
                }
        } else if (dev->ops->max_phys_sect > 256) {
                pr_info("nvm: max sectors supported is 256.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_init;
        }
 
+       down_write(&nvm_lock);
+       list_add(&dev->devices, &nvm_devices);
+       up_write(&nvm_lock);
+
        return 0;
 err_init:
        kfree(dev);
@@ -341,11 +343,12 @@ void nvm_unregister(char *disk_name)
                return;
        }
 
-       nvm_exit(dev);
-
        down_write(&nvm_lock);
        list_del(&dev->devices);
        up_write(&nvm_lock);
+
+       nvm_exit(dev);
+       kfree(dev);
 }
 EXPORT_SYMBOL(nvm_unregister);
 
@@ -457,11 +460,11 @@ static void nvm_remove_target(struct nvm_target *t)
        lockdep_assert_held(&nvm_lock);
 
        del_gendisk(tdisk);
+       blk_cleanup_queue(q);
+
        if (tt->exit)
                tt->exit(tdisk->private_data);
 
-       blk_cleanup_queue(q);
-
        put_disk(tdisk);
 
        list_del(&t->list);
@@ -541,7 +544,7 @@ static int nvm_configure_show(const char *val)
        if (!dev->mt)
                return 0;
 
-       dev->mt->free_blocks_print(dev);
+       dev->mt->lun_info_print(dev);
 
        return 0;
 }
index ae1fb2bdc5f44b25aecdf010afdf9894de0dfede..e20e74ec6b9163dc401149030c7432b4cca12a22 100644 (file)
@@ -60,23 +60,28 @@ static int gennvm_luns_init(struct nvm_dev *dev, struct gen_nvm *gn)
                lun->vlun.lun_id = i % dev->luns_per_chnl;
                lun->vlun.chnl_id = i / dev->luns_per_chnl;
                lun->vlun.nr_free_blocks = dev->blks_per_lun;
+               lun->vlun.nr_inuse_blocks = 0;
+               lun->vlun.nr_bad_blocks = 0;
        }
        return 0;
 }
 
-static int gennvm_block_bb(u32 lun_id, void *bb_bitmap, unsigned int nr_blocks,
+static int gennvm_block_bb(struct ppa_addr ppa, int nr_blocks, u8 *blks,
                                                                void *private)
 {
        struct gen_nvm *gn = private;
-       struct gen_lun *lun = &gn->luns[lun_id];
+       struct nvm_dev *dev = gn->dev;
+       struct gen_lun *lun;
        struct nvm_block *blk;
        int i;
 
-       if (unlikely(bitmap_empty(bb_bitmap, nr_blocks)))
-               return 0;
+       ppa = dev_to_generic_addr(gn->dev, ppa);
+       lun = &gn->luns[(dev->nr_luns * ppa.g.ch) + ppa.g.lun];
+
+       for (i = 0; i < nr_blocks; i++) {
+               if (blks[i] == 0)
+                       continue;
 
-       i = -1;
-       while ((i = find_next_bit(bb_bitmap, nr_blocks, i + 1)) < nr_blocks) {
                blk = &lun->vlun.blocks[i];
                if (!blk) {
                        pr_err("gennvm: BB data is out of bounds.\n");
@@ -84,6 +89,7 @@ static int gennvm_block_bb(u32 lun_id, void *bb_bitmap, unsigned int nr_blocks,
                }
 
                list_move_tail(&blk->list, &lun->bb_list);
+               lun->vlun.nr_bad_blocks++;
        }
 
        return 0;
@@ -136,6 +142,7 @@ static int gennvm_block_map(u64 slba, u32 nlb, __le64 *entries, void *private)
                        list_move_tail(&blk->list, &lun->used_list);
                        blk->type = 1;
                        lun->vlun.nr_free_blocks--;
+                       lun->vlun.nr_inuse_blocks++;
                }
        }
 
@@ -164,15 +171,25 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn)
                        block->id = cur_block_id++;
 
                        /* First block is reserved for device */
-                       if (unlikely(lun_iter == 0 && blk_iter == 0))
+                       if (unlikely(lun_iter == 0 && blk_iter == 0)) {
+                               lun->vlun.nr_free_blocks--;
                                continue;
+                       }
 
                        list_add_tail(&block->list, &lun->free_list);
                }
 
                if (dev->ops->get_bb_tbl) {
-                       ret = dev->ops->get_bb_tbl(dev->q, lun->vlun.id,
-                                       dev->blks_per_lun, gennvm_block_bb, gn);
+                       struct ppa_addr ppa;
+
+                       ppa.ppa = 0;
+                       ppa.g.ch = lun->vlun.chnl_id;
+                       ppa.g.lun = lun->vlun.id;
+                       ppa = generic_to_dev_addr(dev, ppa);
+
+                       ret = dev->ops->get_bb_tbl(dev->q, ppa,
+                                               dev->blks_per_lun,
+                                               gennvm_block_bb, gn);
                        if (ret)
                                pr_err("gennvm: could not read BB table\n");
                }
@@ -199,6 +216,7 @@ static int gennvm_register(struct nvm_dev *dev)
        if (!gn)
                return -ENOMEM;
 
+       gn->dev = dev;
        gn->nr_luns = dev->nr_luns;
        dev->mp = gn;
 
@@ -254,6 +272,7 @@ static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
        blk->type = 1;
 
        lun->vlun.nr_free_blocks--;
+       lun->vlun.nr_inuse_blocks++;
 
        spin_unlock(&vlun->lock);
 out:
@@ -271,16 +290,21 @@ static void gennvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk)
        case 1:
                list_move_tail(&blk->list, &lun->free_list);
                lun->vlun.nr_free_blocks++;
+               lun->vlun.nr_inuse_blocks--;
                blk->type = 0;
                break;
        case 2:
                list_move_tail(&blk->list, &lun->bb_list);
+               lun->vlun.nr_bad_blocks++;
+               lun->vlun.nr_inuse_blocks--;
                break;
        default:
                WARN_ON_ONCE(1);
                pr_err("gennvm: erroneous block type (%lu -> %u)\n",
                                                        blk->id, blk->type);
                list_move_tail(&blk->list, &lun->bb_list);
+               lun->vlun.nr_bad_blocks++;
+               lun->vlun.nr_inuse_blocks--;
        }
 
        spin_unlock(&vlun->lock);
@@ -292,10 +316,10 @@ static void gennvm_addr_to_generic_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
 
        if (rqd->nr_pages > 1) {
                for (i = 0; i < rqd->nr_pages; i++)
-                       rqd->ppa_list[i] = addr_to_generic_mode(dev,
+                       rqd->ppa_list[i] = dev_to_generic_addr(dev,
                                                        rqd->ppa_list[i]);
        } else {
-               rqd->ppa_addr = addr_to_generic_mode(dev, rqd->ppa_addr);
+               rqd->ppa_addr = dev_to_generic_addr(dev, rqd->ppa_addr);
        }
 }
 
@@ -305,10 +329,10 @@ static void gennvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
 
        if (rqd->nr_pages > 1) {
                for (i = 0; i < rqd->nr_pages; i++)
-                       rqd->ppa_list[i] = generic_to_addr_mode(dev,
+                       rqd->ppa_list[i] = generic_to_dev_addr(dev,
                                                        rqd->ppa_list[i]);
        } else {
-               rqd->ppa_addr = generic_to_addr_mode(dev, rqd->ppa_addr);
+               rqd->ppa_addr = generic_to_dev_addr(dev, rqd->ppa_addr);
        }
 }
 
@@ -354,10 +378,10 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
        int i;
 
-       if (!dev->ops->set_bb)
+       if (!dev->ops->set_bb_tbl)
                return;
 
-       if (dev->ops->set_bb(dev->q, rqd, 1))
+       if (dev->ops->set_bb_tbl(dev->q, rqd, 1))
                return;
 
        gennvm_addr_to_generic_mode(dev, rqd);
@@ -440,15 +464,24 @@ static struct nvm_lun *gennvm_get_lun(struct nvm_dev *dev, int lunid)
        return &gn->luns[lunid].vlun;
 }
 
-static void gennvm_free_blocks_print(struct nvm_dev *dev)
+static void gennvm_lun_info_print(struct nvm_dev *dev)
 {
        struct gen_nvm *gn = dev->mp;
        struct gen_lun *lun;
        unsigned int i;
 
-       gennvm_for_each_lun(gn, lun, i)
-               pr_info("%s: lun%8u\t%u\n",
-                                       dev->name, i, lun->vlun.nr_free_blocks);
+
+       gennvm_for_each_lun(gn, lun, i) {
+               spin_lock(&lun->vlun.lock);
+
+               pr_info("%s: lun%8u\t%u\t%u\t%u\n",
+                               dev->name, i,
+                               lun->vlun.nr_free_blocks,
+                               lun->vlun.nr_inuse_blocks,
+                               lun->vlun.nr_bad_blocks);
+
+               spin_unlock(&lun->vlun.lock);
+       }
 }
 
 static struct nvmm_type gennvm = {
@@ -466,7 +499,7 @@ static struct nvmm_type gennvm = {
        .erase_blk      = gennvm_erase_blk,
 
        .get_lun        = gennvm_get_lun,
-       .free_blocks_print = gennvm_free_blocks_print,
+       .lun_info_print = gennvm_lun_info_print,
 };
 
 static int __init gennvm_module_init(void)
index d23bd3501ddc4e56abc8ce177e0fd82aa94fec13..9c24b5b32dac2cb37acc39a5d7c54449296fe231 100644 (file)
@@ -35,6 +35,8 @@ struct gen_lun {
 };
 
 struct gen_nvm {
+       struct nvm_dev *dev;
+
        int nr_luns;
        struct gen_lun *luns;
 };
index 7ba64c87ba1c10306c9b96d132f0d2f869a628da..75e59c3a3f96d821d93600f2ca698a50e2874182 100644 (file)
@@ -123,12 +123,42 @@ static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
        return blk->id * rrpc->dev->pgs_per_blk;
 }
 
+static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev,
+                                                       struct ppa_addr r)
+{
+       struct ppa_addr l;
+       int secs, pgs, blks, luns;
+       sector_t ppa = r.ppa;
+
+       l.ppa = 0;
+
+       div_u64_rem(ppa, dev->sec_per_pg, &secs);
+       l.g.sec = secs;
+
+       sector_div(ppa, dev->sec_per_pg);
+       div_u64_rem(ppa, dev->sec_per_blk, &pgs);
+       l.g.pg = pgs;
+
+       sector_div(ppa, dev->pgs_per_blk);
+       div_u64_rem(ppa, dev->blks_per_lun, &blks);
+       l.g.blk = blks;
+
+       sector_div(ppa, dev->blks_per_lun);
+       div_u64_rem(ppa, dev->luns_per_chnl, &luns);
+       l.g.lun = luns;
+
+       sector_div(ppa, dev->luns_per_chnl);
+       l.g.ch = ppa;
+
+       return l;
+}
+
 static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr)
 {
        struct ppa_addr paddr;
 
        paddr.ppa = addr;
-       return __linear_to_generic_addr(dev, paddr);
+       return linear_to_generic_addr(dev, paddr);
 }
 
 /* requires lun->lock taken */
index 917d47e290ae08be08f4c964a3326f1f67acd077..3147c8d09ea84a0a76d0fd7ead35931a89e29aed 100644 (file)
@@ -112,7 +112,8 @@ struct iv_tcw_private {
  * and encrypts / decrypts at the same time.
  */
 enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID,
-            DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD };
+            DM_CRYPT_SAME_CPU, DM_CRYPT_NO_OFFLOAD,
+            DM_CRYPT_EXIT_THREAD};
 
 /*
  * The fields in here must be read only after initialization.
@@ -1203,20 +1204,18 @@ static int dmcrypt_write(void *data)
                if (!RB_EMPTY_ROOT(&cc->write_tree))
                        goto pop_from_list;
 
+               if (unlikely(test_bit(DM_CRYPT_EXIT_THREAD, &cc->flags))) {
+                       spin_unlock_irq(&cc->write_thread_wait.lock);
+                       break;
+               }
+
                __set_current_state(TASK_INTERRUPTIBLE);
                __add_wait_queue(&cc->write_thread_wait, &wait);
 
                spin_unlock_irq(&cc->write_thread_wait.lock);
 
-               if (unlikely(kthread_should_stop())) {
-                       set_task_state(current, TASK_RUNNING);
-                       remove_wait_queue(&cc->write_thread_wait, &wait);
-                       break;
-               }
-
                schedule();
 
-               set_task_state(current, TASK_RUNNING);
                spin_lock_irq(&cc->write_thread_wait.lock);
                __remove_wait_queue(&cc->write_thread_wait, &wait);
                goto continue_locked;
@@ -1531,8 +1530,13 @@ static void crypt_dtr(struct dm_target *ti)
        if (!cc)
                return;
 
-       if (cc->write_thread)
+       if (cc->write_thread) {
+               spin_lock_irq(&cc->write_thread_wait.lock);
+               set_bit(DM_CRYPT_EXIT_THREAD, &cc->flags);
+               wake_up_locked(&cc->write_thread_wait);
+               spin_unlock_irq(&cc->write_thread_wait.lock);
                kthread_stop(cc->write_thread);
+       }
 
        if (cc->io_queue)
                destroy_workqueue(cc->io_queue);
index aaa6caa46a9f2dbceaf3d9c1aac92037b3b731b2..cfa29f574c2a9e1454788a5757471835b254d857 100644 (file)
@@ -1537,32 +1537,34 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
                struct block_device **bdev, fmode_t *mode)
 {
        struct multipath *m = ti->private;
-       struct pgpath *pgpath;
        unsigned long flags;
        int r;
 
-       r = 0;
-
        spin_lock_irqsave(&m->lock, flags);
 
        if (!m->current_pgpath)
                __choose_pgpath(m, 0);
 
-       pgpath = m->current_pgpath;
-
-       if (pgpath) {
-               *bdev = pgpath->path.dev->bdev;
-               *mode = pgpath->path.dev->mode;
+       if (m->current_pgpath) {
+               if (!m->queue_io) {
+                       *bdev = m->current_pgpath->path.dev->bdev;
+                       *mode = m->current_pgpath->path.dev->mode;
+                       r = 0;
+               } else {
+                       /* pg_init has not started or completed */
+                       r = -ENOTCONN;
+               }
+       } else {
+               /* No path is available */
+               if (m->queue_if_no_path)
+                       r = -ENOTCONN;
+               else
+                       r = -EIO;
        }
 
-       if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
-               r = -ENOTCONN;
-       else if (!*bdev)
-               r = -EIO;
-
        spin_unlock_irqrestore(&m->lock, flags);
 
-       if (r == -ENOTCONN && !fatal_signal_pending(current)) {
+       if (r == -ENOTCONN) {
                spin_lock_irqsave(&m->lock, flags);
                if (!m->current_pg) {
                        /* Path status changed, redo selection */
index 3897b90bd462d852e0aec27a792be14655efa150..63903a5a5d9ee3b580d552673b42b9716b99322c 100644 (file)
@@ -2432,6 +2432,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
        case PM_WRITE:
                if (old_mode != new_mode)
                        notify_of_pool_mode_change(pool, "write");
+               pool->pf.error_if_no_space = pt->requested_pf.error_if_no_space;
                dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
                pool->process_discard = process_discard_bio;
@@ -4249,10 +4250,9 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct thin_c *tc = ti->private;
        struct pool *pool = tc->pool;
-       struct queue_limits *pool_limits = dm_get_queue_limits(pool->pool_md);
 
-       if (!pool_limits->discard_granularity)
-               return; /* pool's discard support is disabled */
+       if (!pool->pf.discard_enabled)
+               return;
 
        limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
        limits->max_discard_sectors = 2048 * 1024 * 16; /* 16G */
index 6e15f3565892fce8315cef992e0b2721e8c20088..5df40480228b7a26e3c73ac78e963ce47ed25448 100644 (file)
@@ -591,7 +591,7 @@ static int dm_get_live_table_for_ioctl(struct mapped_device *md,
 
 out:
        dm_put_live_table(md, *srcu_idx);
-       if (r == -ENOTCONN) {
+       if (r == -ENOTCONN && !fatal_signal_pending(current)) {
                msleep(10);
                goto retry;
        }
@@ -603,9 +603,10 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
 {
        struct mapped_device *md = bdev->bd_disk->private_data;
        struct dm_target *tgt;
+       struct block_device *tgt_bdev = NULL;
        int srcu_idx, r;
 
-       r = dm_get_live_table_for_ioctl(md, &tgt, &bdev, &mode, &srcu_idx);
+       r = dm_get_live_table_for_ioctl(md, &tgt, &tgt_bdev, &mode, &srcu_idx);
        if (r < 0)
                return r;
 
@@ -620,7 +621,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
                        goto out;
        }
 
-       r =  __blkdev_driver_ioctl(bdev, mode, cmd, arg);
+       r =  __blkdev_driver_ioctl(tgt_bdev, mode, cmd, arg);
 out:
        dm_put_live_table(md, srcu_idx);
        return r;
index 35759a91d47dce2eaede0d0491910aeb0180cab7..e8f847226a199f308394302b1f24dacf186b6226 100644 (file)
@@ -1992,9 +1992,9 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
                (unsigned long long)pci_resource_start(pci_dev, 0));
 
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+       err = pci_set_dma_mask(pci_dev, 0xffffffff);
+       if (err) {
                printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
                goto fail_context;
        }
 
index dbc695f327607285162a6f6482582f5fe1857ff8..0042803a9de7c4aaa0eabb375eaf58ccb3056f88 100644 (file)
@@ -1319,7 +1319,8 @@ static int cx25821_initdev(struct pci_dev *pci_dev,
                dev->pci_lat, (unsigned long long)dev->base_io_addr);
 
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+       err = pci_set_dma_mask(pci_dev, 0xffffffff);
+       if (err) {
                pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
                err = -EIO;
                goto fail_irq;
index 0ed1b65303746d3b5129997dc37dd00cbe784716..1b5268f9bb248f5b0787d16e707c25b84ffbe150 100644 (file)
@@ -890,9 +890,9 @@ static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
                return err;
        }
 
-       if (!pci_set_dma_mask(pci,DMA_BIT_MASK(32))) {
+       err = pci_set_dma_mask(pci,DMA_BIT_MASK(32));
+       if (err) {
                dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
-               err = -EIO;
                cx88_core_put(core, pci);
                return err;
        }
index 9db7767d1fe03eaad3244993d193f1045cb5f92b..f34c229f9b374d3dedd424bb54bc2119b0ee0607 100644 (file)
@@ -393,7 +393,8 @@ static int cx8802_init_common(struct cx8802_dev *dev)
        if (pci_enable_device(dev->pci))
                return -EIO;
        pci_set_master(dev->pci);
-       if (!pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32))) {
+       err = pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32));
+       if (err) {
                printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
                return -EIO;
        }
index 0de1ad5a977d4d7b629819bb2d0ee0fb54539bb3..aef9acf351f6379017f967538a87d103fc7b7a94 100644 (file)
@@ -1314,9 +1314,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
               dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
 
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32))) {
+       err = pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32));
+       if (err) {
                printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
-               err = -EIO;
                goto fail_core;
        }
        dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
index 60b2d462f98d0ea92a3738d45919dce57c3c9daf..3fdbd81b558060c1029c6bf621a45d2aa9fd9016 100644 (file)
@@ -810,7 +810,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
                "%s(): board vendor 0x%x, revision 0x%x\n",
                __func__, board_vendor, board_revision);
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+       if (pci_set_dma_mask(pci_dev, 0xffffffff) < 0) {
                dev_err(&pci_dev->dev,
                        "%s(): 32bit PCI DMA is not supported\n", __func__);
                goto pci_detect_err;
index e79d63eb774e338898584ee33fa8476b0cb5b2cf..f720cea80e28ae553183c16a56d2620dd70ab303 100644 (file)
@@ -951,9 +951,9 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
               pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
               dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
+       err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+       if (err) {
                pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
                goto fail1;
        }
 
index 8f36b48ef7338c13ae265f9d424e05348d389f6f..8bbd092fbe1db70052857584f598c3d0192236f3 100644 (file)
@@ -1264,9 +1264,9 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
 
        pci_set_master(pci_dev);
        /* TODO */
-       if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
+       err = pci_set_dma_mask(pci_dev, 0xffffffff);
+       if (err) {
                printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
                goto fail_irq;
        }
 
index 8c5655d351d35c4d1b82ca8f84390c32f31b0306..4e77618fbb2b9aa742de7bdcc218ab1f5feb7f3d 100644 (file)
@@ -257,9 +257,9 @@ static int tw68_initdev(struct pci_dev *pci_dev,
                dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
                dev->pci_lat, (u64)pci_resource_start(pci_dev, 0));
        pci_set_master(pci_dev);
-       if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
+       err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+       if (err) {
                pr_info("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
                goto fail1;
        }
 
index fc73937290812df292d9654ed43ec19f40497edf..02b5f69e1a423f2dd44eede58aaf010d55f3c9d9 100644 (file)
@@ -1038,6 +1038,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,
        int              i, buflist_ent;
        int              sg_spill = MAX_FRAGS_SPILL1;
        int              dir;
+
+       if (bytes < 0)
+               return NULL;
+
        /* initialization */
        *frags = 0;
        *blp = NULL;
index 005a88b9f44029c42b2c700fa4e275482039c47f..7ebccfa8072a7ff8075ab2e71197713afc397dcf 100644 (file)
@@ -1994,7 +1994,6 @@ static struct scsi_host_template mptsas_driver_template = {
        .cmd_per_lun                    = 7,
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = mptscsih_host_attrs,
-       .use_blk_tags                   = 1,
 };
 
 static int mptsas_get_linkerrors(struct sas_phy *phy)
index b8374cdaf9c940ab202821bbaa76e6923f360c84..ee120dcbb3e6ba9b842859496d565129d66c1fd8 100644 (file)
@@ -220,11 +220,17 @@ static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
 /*
  * configfs interfaces show/store functions
  */
-static ssize_t pcie_gadget_show_link(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+
+static struct pcie_gadget_target *to_target(struct config_item *item)
 {
-       struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+       return item ?
+               container_of(to_configfs_subsystem(to_config_group(item)),
+                               struct pcie_gadget_target, subsys) : NULL;
+}
+
+static ssize_t pcie_gadget_link_show(struct config_item *item, char *buf)
+{
+       struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
 
        if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
                return sprintf(buf, "UP");
@@ -232,11 +238,10 @@ static ssize_t pcie_gadget_show_link(
                return sprintf(buf, "DOWN");
 }
 
-static ssize_t pcie_gadget_store_link(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_link_store(struct config_item *item,
                const char *buf, size_t count)
 {
-       struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+       struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
 
        if (sysfs_streq(buf, "UP"))
                writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
@@ -250,17 +255,15 @@ static ssize_t pcie_gadget_store_link(
        return count;
 }
 
-static ssize_t pcie_gadget_show_int_type(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_int_type_show(struct config_item *item, char *buf)
 {
-       return sprintf(buf, "%s", config->int_type);
+       return sprintf(buf, "%s", to_target(item)->int_type);
 }
 
-static ssize_t pcie_gadget_store_int_type(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_int_type_store(struct config_item *item,
                const char *buf, size_t count)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        u32 cap, vec, flags;
        ulong vector;
 
@@ -288,11 +291,10 @@ static ssize_t pcie_gadget_store_int_type(
        return count;
 }
 
-static ssize_t pcie_gadget_show_no_of_msi(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_no_of_msi_show(struct config_item *item, char *buf)
 {
-       struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+       struct spear_pcie_gadget_config *config = to_target(item)
+       struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
        u32 cap, vec, flags;
        ulong vector;
 
@@ -313,13 +315,12 @@ static ssize_t pcie_gadget_show_no_of_msi(
        return sprintf(buf, "%lu", vector);
 }
 
-static ssize_t pcie_gadget_store_no_of_msi(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_no_of_msi_store(struct config_item *item,
                const char *buf, size_t count)
 {
        int ret;
 
-       ret = kstrtoul(buf, 0, &config->requested_msi);
+       ret = kstrtoul(buf, 0, &to_target(item)->requested_msi);
        if (ret)
                return ret;
 
@@ -329,11 +330,10 @@ static ssize_t pcie_gadget_store_no_of_msi(
        return count;
 }
 
-static ssize_t pcie_gadget_store_inta(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_inta_store(struct config_item *item,
                const char *buf, size_t count)
 {
-       struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+       struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
        ulong en;
        int ret;
 
@@ -351,10 +351,10 @@ static ssize_t pcie_gadget_store_inta(
        return count;
 }
 
-static ssize_t pcie_gadget_store_send_msi(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_send_msi_store(struct config_item *item,
                const char *buf, size_t count)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
        ulong vector;
        u32 ven_msi;
@@ -388,19 +388,16 @@ static ssize_t pcie_gadget_store_send_msi(
        return count;
 }
 
-static ssize_t pcie_gadget_show_vendor_id(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_vendor_id_show(struct config_item *item, char *buf)
 {
        u32 id;
 
-       spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
+       spear_dbi_read_reg(to_target(item), PCI_VENDOR_ID, 2, &id);
 
        return sprintf(buf, "%x", id);
 }
 
-static ssize_t pcie_gadget_store_vendor_id(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_vendor_id_store(struct config_item *item,
                const char *buf, size_t count)
 {
        ulong id;
@@ -410,24 +407,21 @@ static ssize_t pcie_gadget_store_vendor_id(
        if (ret)
                return ret;
 
-       spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
+       spear_dbi_write_reg(to_target(item), PCI_VENDOR_ID, 2, id);
 
        return count;
 }
 
-static ssize_t pcie_gadget_show_device_id(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_device_id_show(struct config_item *item, char *buf)
 {
        u32 id;
 
-       spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
+       spear_dbi_read_reg(to_target(item), PCI_DEVICE_ID, 2, &id);
 
        return sprintf(buf, "%x", id);
 }
 
-static ssize_t pcie_gadget_store_device_id(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_device_id_store(struct config_item *item,
                const char *buf, size_t count)
 {
        ulong id;
@@ -437,22 +431,20 @@ static ssize_t pcie_gadget_store_device_id(
        if (ret)
                return ret;
 
-       spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
+       spear_dbi_write_reg(to_target(item), PCI_DEVICE_ID, 2, id);
 
        return count;
 }
 
-static ssize_t pcie_gadget_show_bar0_size(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_bar0_size_show(struct config_item *item, char *buf)
 {
-       return sprintf(buf, "%lx", config->bar0_size);
+       return sprintf(buf, "%lx", to_target(item)->bar0_size);
 }
 
-static ssize_t pcie_gadget_store_bar0_size(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_size_store(struct config_item *item,
                const char *buf, size_t count)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        ulong size;
        u32 pos, pos1;
        u32 no_of_bit = 0;
@@ -489,21 +481,20 @@ static ssize_t pcie_gadget_store_bar0_size(
        return count;
 }
 
-static ssize_t pcie_gadget_show_bar0_address(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_address_show(struct config_item *item,
                char *buf)
 {
-       struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+       struct pcie_app_reg __iomem *app_reg = to_target(item)->va_app_base;
 
        u32 address = readl(&app_reg->pim0_mem_addr_start);
 
        return sprintf(buf, "%x", address);
 }
 
-static ssize_t pcie_gadget_store_bar0_address(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_address_store(struct config_item *item,
                const char *buf, size_t count)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        struct pcie_app_reg __iomem *app_reg = config->va_app_base;
        ulong address;
        int ret;
@@ -524,15 +515,13 @@ static ssize_t pcie_gadget_store_bar0_address(
        return count;
 }
 
-static ssize_t pcie_gadget_show_bar0_rw_offset(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_rw_offset_show(struct config_item *item,
                char *buf)
 {
-       return sprintf(buf, "%lx", config->bar0_rw_offset);
+       return sprintf(buf, "%lx", to_target(item)->bar0_rw_offset);
 }
 
-static ssize_t pcie_gadget_store_bar0_rw_offset(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_rw_offset_store(struct config_item *item,
                const char *buf, size_t count)
 {
        ulong offset;
@@ -545,15 +534,14 @@ static ssize_t pcie_gadget_store_bar0_rw_offset(
        if (offset % 4)
                return -EINVAL;
 
-       config->bar0_rw_offset = offset;
+       to_target(item)->bar0_rw_offset = offset;
 
        return count;
 }
 
-static ssize_t pcie_gadget_show_bar0_data(
-               struct spear_pcie_gadget_config *config,
-               char *buf)
+static ssize_t pcie_gadget_bar0_data_show(struct config_item *item, char *buf)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        ulong data;
 
        if (!config->va_bar0_address)
@@ -564,10 +552,10 @@ static ssize_t pcie_gadget_show_bar0_data(
        return sprintf(buf, "%lx", data);
 }
 
-static ssize_t pcie_gadget_store_bar0_data(
-               struct spear_pcie_gadget_config *config,
+static ssize_t pcie_gadget_bar0_data_store(struct config_item *item,
                const char *buf, size_t count)
 {
+       struct spear_pcie_gadget_config *config = to_target(item)
        ulong data;
        int ret;
 
@@ -583,97 +571,35 @@ static ssize_t pcie_gadget_store_bar0_data(
        return count;
 }
 
-/*
- * Attribute definitions.
- */
-
-#define PCIE_GADGET_TARGET_ATTR_RO(_name)                              \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name =     \
-       __CONFIGFS_ATTR(_name, S_IRUGO, pcie_gadget_show_##_name, NULL)
-
-#define PCIE_GADGET_TARGET_ATTR_WO(_name)                              \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name =     \
-       __CONFIGFS_ATTR(_name, S_IWUSR, NULL, pcie_gadget_store_##_name)
-
-#define PCIE_GADGET_TARGET_ATTR_RW(_name)                              \
-static struct pcie_gadget_target_attr pcie_gadget_target_##_name =     \
-       __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, pcie_gadget_show_##_name, \
-                       pcie_gadget_store_##_name)
-PCIE_GADGET_TARGET_ATTR_RW(link);
-PCIE_GADGET_TARGET_ATTR_RW(int_type);
-PCIE_GADGET_TARGET_ATTR_RW(no_of_msi);
-PCIE_GADGET_TARGET_ATTR_WO(inta);
-PCIE_GADGET_TARGET_ATTR_WO(send_msi);
-PCIE_GADGET_TARGET_ATTR_RW(vendor_id);
-PCIE_GADGET_TARGET_ATTR_RW(device_id);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_size);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_address);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_rw_offset);
-PCIE_GADGET_TARGET_ATTR_RW(bar0_data);
+CONFIGFS_ATTR(pcie_gadget_, link);
+CONFIGFS_ATTR(pcie_gadget_, int_type);
+CONFIGFS_ATTR(pcie_gadget_, no_of_msi);
+CONFIGFS_ATTR_WO(pcie_gadget_, inta);
+CONFIGFS_ATTR_WO(pcie_gadget_, send_msi);
+CONFIGFS_ATTR(pcie_gadget_, vendor_id);
+CONFIGFS_ATTR(pcie_gadget_, device_id);
+CONFIGFS_ATTR(pcie_gadget_, bar0_size);
+CONFIGFS_ATTR(pcie_gadget_, bar0_address);
+CONFIGFS_ATTR(pcie_gadget_, bar0_rw_offset);
+CONFIGFS_ATTR(pcie_gadget_, bar0_data);
 
 static struct configfs_attribute *pcie_gadget_target_attrs[] = {
-       &pcie_gadget_target_link.attr,
-       &pcie_gadget_target_int_type.attr,
-       &pcie_gadget_target_no_of_msi.attr,
-       &pcie_gadget_target_inta.attr,
-       &pcie_gadget_target_send_msi.attr,
-       &pcie_gadget_target_vendor_id.attr,
-       &pcie_gadget_target_device_id.attr,
-       &pcie_gadget_target_bar0_size.attr,
-       &pcie_gadget_target_bar0_address.attr,
-       &pcie_gadget_target_bar0_rw_offset.attr,
-       &pcie_gadget_target_bar0_data.attr,
+       &pcie_gadget_attr_link,
+       &pcie_gadget_attr_int_type,
+       &pcie_gadget_attr_no_of_msi,
+       &pcie_gadget_attr_inta,
+       &pcie_gadget_attr_send_msi,
+       &pcie_gadget_attr_vendor_id,
+       &pcie_gadget_attr_device_id,
+       &pcie_gadget_attr_bar0_size,
+       &pcie_gadget_attr_bar0_address,
+       &pcie_gadget_attr_bar0_rw_offset,
+       &pcie_gadget_attr_bar0_data,
        NULL,
 };
 
-static struct pcie_gadget_target *to_target(struct config_item *item)
-{
-       return item ?
-               container_of(to_configfs_subsystem(to_config_group(item)),
-                               struct pcie_gadget_target, subsys) : NULL;
-}
-
-/*
- * Item operations and type for pcie_gadget_target.
- */
-
-static ssize_t pcie_gadget_target_attr_show(struct config_item *item,
-                                          struct configfs_attribute *attr,
-                                          char *buf)
-{
-       ssize_t ret = -EINVAL;
-       struct pcie_gadget_target *target = to_target(item);
-       struct pcie_gadget_target_attr *t_attr =
-               container_of(attr, struct pcie_gadget_target_attr, attr);
-
-       if (t_attr->show)
-               ret = t_attr->show(&target->config, buf);
-       return ret;
-}
-
-static ssize_t pcie_gadget_target_attr_store(struct config_item *item,
-                                       struct configfs_attribute *attr,
-                                       const char *buf,
-                                       size_t count)
-{
-       ssize_t ret = -EINVAL;
-       struct pcie_gadget_target *target = to_target(item);
-       struct pcie_gadget_target_attr *t_attr =
-               container_of(attr, struct pcie_gadget_target_attr, attr);
-
-       if (t_attr->store)
-               ret = t_attr->store(&target->config, buf, count);
-       return ret;
-}
-
-static struct configfs_item_operations pcie_gadget_target_item_ops = {
-       .show_attribute         = pcie_gadget_target_attr_show,
-       .store_attribute        = pcie_gadget_target_attr_store,
-};
-
 static struct config_item_type pcie_gadget_target_type = {
        .ct_attrs               = pcie_gadget_target_attrs,
-       .ct_item_ops            = &pcie_gadget_target_item_ops,
        .ct_owner               = THIS_MODULE,
 };
 
index 23b6c8e8701ccd6e3ec57c85483276de4b02f51b..d8486168415ae1123f6a31d7126cfc9192fe884b 100644 (file)
@@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block");
 #define MMC_SANITIZE_REQ_TIMEOUT 240000
 #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
 
-#define mmc_req_rel_wr(req)    (((req->cmd_flags & REQ_FUA) || \
-                                 (req->cmd_flags & REQ_META)) && \
+#define mmc_req_rel_wr(req)    ((req->cmd_flags & REQ_FUA) && \
                                  (rq_data_dir(req) == WRITE))
 #define PACKED_CMD_VER 0x01
 #define PACKED_CMD_WR  0x02
@@ -1467,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 
        /*
         * Reliable writes are used to implement Forced Unit Access and
-        * REQ_META accesses, and are supported only on MMCs.
-        *
-        * XXX: this really needs a good explanation of why REQ_META
-        * is treated special.
+        * are supported only on MMCs.
         */
-       bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
-                         (req->cmd_flags & REQ_META)) &&
+       bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&
                (rq_data_dir(req) == WRITE) &&
                (md->flags & MMC_BLK_REL_WR);
 
index c793fda27321da0086bb01d92e33d9aa44480ed0..3a9a79ec4343cd0f9f71158768e5707340def684 100644 (file)
@@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
        return err;
 }
 
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+       u32 status;
+       int err;
+
+       err = mmc_send_status(card, &status);
+       if (err)
+               return err;
+
+       return mmc_switch_status_error(card->host, status);
+}
+
 static int mmc_select_hs400(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
+       bool send_status = true;
+       unsigned int max_dtr;
        int err = 0;
        u8 val;
 
@@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card)
              host->ios.bus_width == MMC_BUS_WIDTH_8))
                return 0;
 
-       /*
-        * Before switching to dual data rate operation for HS400,
-        * it is required to convert from HS200 mode to HS mode.
-        */
-       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-       mmc_set_bus_speed(card);
+       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+               send_status = false;
 
+       /* Reduce frequency to HS frequency */
+       max_dtr = card->ext_csd.hs_max_dtr;
+       mmc_set_clock(host, max_dtr);
+
+       /* Switch card to HS mode */
        val = EXT_CSD_TIMING_HS |
              card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                           EXT_CSD_HS_TIMING, val,
                           card->ext_csd.generic_cmd6_time,
-                          true, true, true);
+                          true, send_status, true);
        if (err) {
                pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
                        mmc_hostname(host), err);
                return err;
        }
 
+       /* Set host controller to HS timing */
+       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+
+       if (!send_status) {
+               err = mmc_switch_status(card);
+               if (err)
+                       goto out_err;
+       }
+
+       /* Switch card to DDR */
        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                         EXT_CSD_BUS_WIDTH,
                         EXT_CSD_DDR_BUS_WIDTH_8,
@@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)
                return err;
        }
 
+       /* Switch card to HS400 */
        val = EXT_CSD_TIMING_HS400 |
              card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                           EXT_CSD_HS_TIMING, val,
                           card->ext_csd.generic_cmd6_time,
-                          true, true, true);
+                          true, send_status, true);
        if (err) {
                pr_err("%s: switch to hs400 failed, err:%d\n",
                         mmc_hostname(host), err);
                return err;
        }
 
+       /* Set host controller to HS400 timing and frequency */
        mmc_set_timing(host, MMC_TIMING_MMC_HS400);
        mmc_set_bus_speed(card);
 
+       if (!send_status) {
+               err = mmc_switch_status(card);
+               if (err)
+                       goto out_err;
+       }
+
        return 0;
+
+out_err:
+       pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+              __func__, err);
+       return err;
 }
 
 int mmc_hs200_to_hs400(struct mmc_card *card)
@@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
        return mmc_select_hs400(card);
 }
 
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
-       u32 status;
-       int err;
-
-       err = mmc_send_status(card, &status);
-       if (err)
-               return err;
-
-       return mmc_switch_status_error(card->host, status);
-}
-
 int mmc_hs400_to_hs200(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
@@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card)
 static int mmc_select_hs200(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
+       bool send_status = true;
+       unsigned int old_timing;
        int err = -EINVAL;
        u8 val;
 
@@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        mmc_select_driver_type(card);
 
+       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+               send_status = false;
+
        /*
         * Set the bus width(4 or 8) with host's support and
         * switch to HS200 mode if bus width is set successfully.
@@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card)
                err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                   EXT_CSD_HS_TIMING, val,
                                   card->ext_csd.generic_cmd6_time,
-                                  true, true, true);
-               if (!err)
-                       mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+                                  true, send_status, true);
+               if (err)
+                       goto err;
+               old_timing = host->ios.timing;
+               mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+               if (!send_status) {
+                       err = mmc_switch_status(card);
+                       /*
+                        * mmc_select_timing() assumes timing has not changed if
+                        * it is a switch error.
+                        */
+                       if (err == -EBADMSG)
+                               mmc_set_timing(host, old_timing);
+               }
        }
 err:
+       if (err)
+               pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
+                      __func__, err);
        return err;
 }
 
index af71de5fda3b48c99fefd122a0cb6df9af2234ac..1dee533634c986d71176917f4d510a4c7214bf5a 100644 (file)
@@ -473,6 +473,7 @@ config MMC_DAVINCI
 
 config MMC_GOLDFISH
        tristate "goldfish qemu Multimedia Card Interface support"
+       depends on HAS_DMA
        depends on GOLDFISH || COMPILE_TEST
        help
          This selects the Goldfish Multimedia card Interface emulation
index 39568cc29a2a18cf752141dcf6233746b4d149e1..33dfd7e72516c3920b7ec641efb930668f0e15f5 100644 (file)
@@ -1276,7 +1276,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
        int start = 0, len = 0;
        int start_final = 0, len_final = 0;
        u8 final_phase = 0xff;
-       struct msdc_delay_phase delay_phase;
+       struct msdc_delay_phase delay_phase = { 0, };
 
        if (delay == 0) {
                dev_err(host->dev, "phase error: [map:%x]\n", delay);
index 8cadd74e8407bb08d7e277a82ac5d80d496f77e4..ce08896b9d696b00440fe7807aeddf72b922f320 100644 (file)
@@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev)
                goto out;
        } else {
                mmc->caps |= host->pdata->gpio_card_ro_invert ?
-                       MMC_CAP2_RO_ACTIVE_HIGH : 0;
+                       0 : MMC_CAP2_RO_ACTIVE_HIGH;
        }
 
        if (gpio_is_valid(gpio_cd))
index dc4e8446f1ff10b55acf6c40a4cb0ac662cf2b06..5a99a93ed02568f5778f9a55d6a7c4ed6b44cadd 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/gpio.h>
 
+#include <asm/mach-jz4740/gpio.h>
 #include <asm/mach-jz4740/jz4740_nand.h>
 
 #define JZ_REG_NAND_CTRL       0x50
index cc74142938b0a21410cc76e0adca5a58aa1ce26f..ece544efccc3af3a46d73f0825f2ce797d401ae6 100644 (file)
@@ -3110,7 +3110,7 @@ static void nand_resume(struct mtd_info *mtd)
  */
 static void nand_shutdown(struct mtd_info *mtd)
 {
-       nand_get_device(mtd, FL_SHUTDOWN);
+       nand_get_device(mtd, FL_PM_SUSPENDED);
 }
 
 /* Set default functions */
index 9093577755f69bac2c548518922b1b63215a62a6..0527f485c3dc7c4d1cc689a7707820af993bc68f 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/netdevice.h>
 #include <linux/phy.h>
 #include <net/dsa.h>
-
-#define REG_PORT(p)            (8 + (p))
-#define REG_GLOBAL             0x0f
+#include "mv88e6060.h"
 
 static int reg_read(struct dsa_switch *ds, int addr, int reg)
 {
@@ -67,13 +65,14 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
        if (bus == NULL)
                return NULL;
 
-       ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
+       ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
        if (ret >= 0) {
-               if (ret == 0x0600)
+               if (ret == PORT_SWITCH_ID_6060)
                        return "Marvell 88E6060 (A0)";
-               if (ret == 0x0601 || ret == 0x0602)
+               if (ret == PORT_SWITCH_ID_6060_R1 ||
+                   ret == PORT_SWITCH_ID_6060_R2)
                        return "Marvell 88E6060 (B0)";
-               if ((ret & 0xfff0) == 0x0600)
+               if ((ret & PORT_SWITCH_ID_6060_MASK) == PORT_SWITCH_ID_6060)
                        return "Marvell 88E6060";
        }
 
@@ -87,22 +86,26 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds)
        unsigned long timeout;
 
        /* Set all ports to the disabled state. */
-       for (i = 0; i < 6; i++) {
-               ret = REG_READ(REG_PORT(i), 0x04);
-               REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
+       for (i = 0; i < MV88E6060_PORTS; i++) {
+               ret = REG_READ(REG_PORT(i), PORT_CONTROL);
+               REG_WRITE(REG_PORT(i), PORT_CONTROL,
+                         ret & ~PORT_CONTROL_STATE_MASK);
        }
 
        /* Wait for transmit queues to drain. */
        usleep_range(2000, 4000);
 
        /* Reset the switch. */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0xa130);
+       REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
+                 GLOBAL_ATU_CONTROL_SWRESET |
+                 GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
+                 GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
 
        /* Wait up to one second for reset to complete. */
        timeout = jiffies + 1 * HZ;
        while (time_before(jiffies, timeout)) {
-               ret = REG_READ(REG_GLOBAL, 0x00);
-               if ((ret & 0x8000) == 0x0000)
+               ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS);
+               if (ret & GLOBAL_STATUS_INIT_READY)
                        break;
 
                usleep_range(1000, 2000);
@@ -119,13 +122,15 @@ static int mv88e6060_setup_global(struct dsa_switch *ds)
         * set the maximum frame size to 1536 bytes, and mask all
         * interrupt sources.
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x0800);
+       REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536);
 
        /* Enable automatic address learning, set the address
         * database size to 1024 entries, and set the default aging
         * time to 5 minutes.
         */
-       REG_WRITE(REG_GLOBAL, 0x0a, 0x2130);
+       REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL,
+                 GLOBAL_ATU_CONTROL_ATUSIZE_1024 |
+                 GLOBAL_ATU_CONTROL_ATE_AGE_5MIN);
 
        return 0;
 }
@@ -139,25 +144,30 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
         * state to Forwarding.  Additionally, if this is the CPU
         * port, enable Ingress and Egress Trailer tagging mode.
         */
-       REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ?  0x4103 : 0x0003);
+       REG_WRITE(addr, PORT_CONTROL,
+                 dsa_is_cpu_port(ds, p) ?
+                       PORT_CONTROL_TRAILER |
+                       PORT_CONTROL_INGRESS_MODE |
+                       PORT_CONTROL_STATE_FORWARDING :
+                       PORT_CONTROL_STATE_FORWARDING);
 
        /* Port based VLAN map: give each port its own address
         * database, allow the CPU port to talk to each of the 'real'
         * ports, and allow each of the 'real' ports to only talk to
         * the CPU port.
         */
-       REG_WRITE(addr, 0x06,
-                       ((p & 0xf) << 12) |
-                        (dsa_is_cpu_port(ds, p) ?
-                               ds->phys_port_mask :
-                               (1 << ds->dst->cpu_port)));
+       REG_WRITE(addr, PORT_VLAN_MAP,
+                 ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) |
+                  (dsa_is_cpu_port(ds, p) ?
+                       ds->phys_port_mask :
+                       BIT(ds->dst->cpu_port)));
 
        /* Port Association Vector: when learning source addresses
         * of packets, add the address to the address database using
         * a port bitmap that has only the bit for this port set and
         * the other bits clear.
         */
-       REG_WRITE(addr, 0x0b, 1 << p);
+       REG_WRITE(addr, PORT_ASSOC_VECTOR, BIT(p));
 
        return 0;
 }
@@ -177,7 +187,7 @@ static int mv88e6060_setup(struct dsa_switch *ds)
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < MV88E6060_PORTS; i++) {
                ret = mv88e6060_setup_port(ds, i);
                if (ret < 0)
                        return ret;
@@ -188,16 +198,17 @@ static int mv88e6060_setup(struct dsa_switch *ds)
 
 static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr)
 {
-       REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
-       REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
-       REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
+       /* Use the same MAC Address as FD Pause frames for all ports */
+       REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]);
+       REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]);
+       REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]);
 
        return 0;
 }
 
 static int mv88e6060_port_to_phy_addr(int port)
 {
-       if (port >= 0 && port <= 5)
+       if (port >= 0 && port < MV88E6060_PORTS)
                return port;
        return -1;
 }
@@ -225,54 +236,6 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
        return reg_write(ds, addr, regnum, val);
 }
 
-static void mv88e6060_poll_link(struct dsa_switch *ds)
-{
-       int i;
-
-       for (i = 0; i < DSA_MAX_PORTS; i++) {
-               struct net_device *dev;
-               int uninitialized_var(port_status);
-               int link;
-               int speed;
-               int duplex;
-               int fc;
-
-               dev = ds->ports[i];
-               if (dev == NULL)
-                       continue;
-
-               link = 0;
-               if (dev->flags & IFF_UP) {
-                       port_status = reg_read(ds, REG_PORT(i), 0x00);
-                       if (port_status < 0)
-                               continue;
-
-                       link = !!(port_status & 0x1000);
-               }
-
-               if (!link) {
-                       if (netif_carrier_ok(dev)) {
-                               netdev_info(dev, "link down\n");
-                               netif_carrier_off(dev);
-                       }
-                       continue;
-               }
-
-               speed = (port_status & 0x0100) ? 100 : 10;
-               duplex = (port_status & 0x0200) ? 1 : 0;
-               fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0;
-
-               if (!netif_carrier_ok(dev)) {
-                       netdev_info(dev,
-                                   "link up, %d Mb/s, %s duplex, flow control %sabled\n",
-                                   speed,
-                                   duplex ? "full" : "half",
-                                   fc ? "en" : "dis");
-                       netif_carrier_on(dev);
-               }
-       }
-}
-
 static struct dsa_switch_driver mv88e6060_switch_driver = {
        .tag_protocol   = DSA_TAG_PROTO_TRAILER,
        .probe          = mv88e6060_probe,
@@ -280,7 +243,6 @@ static struct dsa_switch_driver mv88e6060_switch_driver = {
        .set_addr       = mv88e6060_set_addr,
        .phy_read       = mv88e6060_phy_read,
        .phy_write      = mv88e6060_phy_write,
-       .poll_link      = mv88e6060_poll_link,
 };
 
 static int __init mv88e6060_init(void)
diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h
new file mode 100644 (file)
index 0000000..cc9b2ed
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * drivers/net/dsa/mv88e6060.h - Marvell 88e6060 switch chip support
+ * Copyright (c) 2015 Neil Armstrong
+ *
+ * Based on mv88e6xxx.h
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MV88E6060_H
+#define __MV88E6060_H
+
+#define MV88E6060_PORTS        6
+
+#define REG_PORT(p)            (0x8 + (p))
+#define PORT_STATUS            0x00
+#define PORT_STATUS_PAUSE_EN   BIT(15)
+#define PORT_STATUS_MY_PAUSE   BIT(14)
+#define PORT_STATUS_FC         (PORT_STATUS_MY_PAUSE | PORT_STATUS_PAUSE_EN)
+#define PORT_STATUS_RESOLVED   BIT(13)
+#define PORT_STATUS_LINK       BIT(12)
+#define PORT_STATUS_PORTMODE   BIT(11)
+#define PORT_STATUS_PHYMODE    BIT(10)
+#define PORT_STATUS_DUPLEX     BIT(9)
+#define PORT_STATUS_SPEED      BIT(8)
+#define PORT_SWITCH_ID         0x03
+#define PORT_SWITCH_ID_6060    0x0600
+#define PORT_SWITCH_ID_6060_MASK       0xfff0
+#define PORT_SWITCH_ID_6060_R1 0x0601
+#define PORT_SWITCH_ID_6060_R2 0x0602
+#define PORT_CONTROL           0x04
+#define PORT_CONTROL_FORCE_FLOW_CTRL   BIT(15)
+#define PORT_CONTROL_TRAILER   BIT(14)
+#define PORT_CONTROL_HEADER    BIT(11)
+#define PORT_CONTROL_INGRESS_MODE      BIT(8)
+#define PORT_CONTROL_VLAN_TUNNEL       BIT(7)
+#define PORT_CONTROL_STATE_MASK        0x03
+#define PORT_CONTROL_STATE_DISABLED    0x00
+#define PORT_CONTROL_STATE_BLOCKING    0x01
+#define PORT_CONTROL_STATE_LEARNING    0x02
+#define PORT_CONTROL_STATE_FORWARDING  0x03
+#define PORT_VLAN_MAP          0x06
+#define PORT_VLAN_MAP_DBNUM_SHIFT      12
+#define PORT_VLAN_MAP_TABLE_MASK       0x1f
+#define PORT_ASSOC_VECTOR      0x0b
+#define PORT_ASSOC_VECTOR_MONITOR      BIT(15)
+#define PORT_ASSOC_VECTOR_PAV_MASK     0x1f
+#define PORT_RX_CNTR           0x10
+#define PORT_TX_CNTR           0x11
+
+#define REG_GLOBAL             0x0f
+#define GLOBAL_STATUS          0x00
+#define GLOBAL_STATUS_SW_MODE_MASK     (0x3 << 12)
+#define GLOBAL_STATUS_SW_MODE_0        (0x0 << 12)
+#define GLOBAL_STATUS_SW_MODE_1        (0x1 << 12)
+#define GLOBAL_STATUS_SW_MODE_2        (0x2 << 12)
+#define GLOBAL_STATUS_SW_MODE_3        (0x3 << 12)
+#define GLOBAL_STATUS_INIT_READY       BIT(11)
+#define GLOBAL_STATUS_ATU_FULL         BIT(3)
+#define GLOBAL_STATUS_ATU_DONE         BIT(2)
+#define GLOBAL_STATUS_PHY_INT  BIT(1)
+#define GLOBAL_STATUS_EEINT    BIT(0)
+#define GLOBAL_MAC_01          0x01
+#define GLOBAL_MAC_01_DIFF_ADDR        BIT(8)
+#define GLOBAL_MAC_23          0x02
+#define GLOBAL_MAC_45          0x03
+#define GLOBAL_CONTROL         0x04
+#define GLOBAL_CONTROL_DISCARD_EXCESS  BIT(13)
+#define GLOBAL_CONTROL_MAX_FRAME_1536  BIT(10)
+#define GLOBAL_CONTROL_RELOAD_EEPROM   BIT(9)
+#define GLOBAL_CONTROL_CTRMODE         BIT(8)
+#define GLOBAL_CONTROL_ATU_FULL_EN     BIT(3)
+#define GLOBAL_CONTROL_ATU_DONE_EN     BIT(2)
+#define GLOBAL_CONTROL_PHYINT_EN       BIT(1)
+#define GLOBAL_CONTROL_EEPROM_DONE_EN  BIT(0)
+#define GLOBAL_ATU_CONTROL     0x0a
+#define GLOBAL_ATU_CONTROL_SWRESET     BIT(15)
+#define GLOBAL_ATU_CONTROL_LEARNDIS    BIT(14)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_256 (0x0 << 12)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_512 (0x1 << 12)
+#define GLOBAL_ATU_CONTROL_ATUSIZE_1024        (0x2 << 12)
+#define GLOBAL_ATU_CONTROL_ATE_AGE_SHIFT       4
+#define GLOBAL_ATU_CONTROL_ATE_AGE_MASK        (0xff << 4)
+#define GLOBAL_ATU_CONTROL_ATE_AGE_5MIN        (0x13 << 4)
+#define GLOBAL_ATU_OP          0x0b
+#define GLOBAL_ATU_OP_BUSY     BIT(15)
+#define GLOBAL_ATU_OP_NOP              (0 << 12)
+#define GLOBAL_ATU_OP_FLUSH_ALL        ((1 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_UNLOCKED   ((2 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_LOAD_DB          ((3 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_GET_NEXT_DB      ((4 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_DB         ((5 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_OP_FLUSH_UNLOCKED_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY)
+#define GLOBAL_ATU_DATA                0x0c
+#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK       0x3f0
+#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT      4
+#define GLOBAL_ATU_DATA_STATE_MASK             0x0f
+#define GLOBAL_ATU_DATA_STATE_UNUSED           0x00
+#define GLOBAL_ATU_DATA_STATE_UC_STATIC                0x0e
+#define GLOBAL_ATU_DATA_STATE_UC_LOCKED                0x0f
+#define GLOBAL_ATU_DATA_STATE_MC_STATIC                0x07
+#define GLOBAL_ATU_DATA_STATE_MC_LOCKED                0x0e
+#define GLOBAL_ATU_MAC_01      0x0d
+#define GLOBAL_ATU_MAC_23      0x0e
+#define GLOBAL_ATU_MAC_45      0x0f
+
+#endif
index 05aa7597dab9b712de711f61c2d14e8bd0e992e6..955d06b9cdba75e82fa87deb26fbb37e08140f87 100644 (file)
@@ -78,7 +78,6 @@ source "drivers/net/ethernet/ibm/Kconfig"
 source "drivers/net/ethernet/intel/Kconfig"
 source "drivers/net/ethernet/i825xx/Kconfig"
 source "drivers/net/ethernet/xscale/Kconfig"
-source "drivers/net/ethernet/icplus/Kconfig"
 
 config JME
        tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
index ddfc808110a161f9adbd33ec6bdf594ba27d2524..4a2ee98738f04ef6eda76d776176dba22a9a7ef0 100644 (file)
@@ -41,7 +41,6 @@ obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
 obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
 obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
 obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
-obj-$(CONFIG_IP1000) += icplus/
 obj-$(CONFIG_JME) += jme.o
 obj-$(CONFIG_KORINA) += korina.o
 obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
index e2afabf3a465860230cbae73d8e37166d30c5394..7ccebae9cb48794cd3977a6fb49844a5bc57e75a 100644 (file)
@@ -1500,10 +1500,11 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       if (!pci_set_dma_mask(pdev, PCNET32_DMA_MASK)) {
+       err = pci_set_dma_mask(pdev, PCNET32_DMA_MASK);
+       if (err) {
                if (pcnet32_debug & NETIF_MSG_PROBE)
                        pr_err("architecture does not support 32bit PCI busmaster DMA\n");
-               return -ENODEV;
+               return err;
        }
        if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) {
                if (pcnet32_debug & NETIF_MSG_PROBE)
index 7dd893331785ebce1740280dfdee1acb13de0a52..618d952c2984c3756cee516fb4623f0cb6a80afd 100644 (file)
@@ -342,6 +342,7 @@ static int xgbe_probe(struct platform_device *pdev)
        struct resource *res;
        const char *phy_mode;
        unsigned int i, phy_memnum, phy_irqnum;
+       enum dev_dma_attr attr;
        int ret;
 
        DBGPR("--> xgbe_probe\n");
@@ -609,7 +610,12 @@ static int xgbe_probe(struct platform_device *pdev)
                goto err_io;
 
        /* Set the DMA coherency values */
-       pdata->coherent = device_dma_is_coherent(pdata->dev);
+       attr = device_get_dma_attr(dev);
+       if (attr == DEV_DMA_NOT_SUPPORTED) {
+               dev_err(dev, "DMA is not supported");
+               goto err_io;
+       }
+       pdata->coherent = (attr == DEV_DMA_COHERENT);
        if (pdata->coherent) {
                pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
                pdata->arcache = XGBE_DMA_OS_ARCACHE;
index f1d62d5dbaff9a83ccacd0a530c855b14209eb7a..c9b036789184e5cadc7a6e9892e1778c2b9b1582 100644 (file)
@@ -13207,7 +13207,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 
        /* VF with OLD Hypervisor or old PF do not support filtering */
        if (IS_PF(bp)) {
-               if (CHIP_IS_E1x(bp))
+               if (chip_is_e1x)
                        bp->accept_any_vlan = true;
                else
                        dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
index f683d97d7614e7414ccf837ead2e2a507b07e4d3..b89504405b7207f12663aee0d6d3ecf78d392235 100644 (file)
@@ -560,7 +560,7 @@ static int liquidio_resume(struct pci_dev *pdev)
 #endif
 
 /* For PCI-E Advanced Error Recovery (AER) Interface */
-static struct pci_error_handlers liquidio_err_handler = {
+static const struct pci_error_handlers liquidio_err_handler = {
        .error_detected = liquidio_pcie_error_detected,
        .mmio_enabled   = liquidio_pcie_mmio_enabled,
        .slot_reset     = liquidio_pcie_slot_reset,
index a9377727c11c3fdb18a09f16ce8366ae4ef48057..7f709cbdcd87d2f0a0beedd338437218ee0af094 100644 (file)
@@ -1583,8 +1583,14 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static void nicvf_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
-       struct nicvf *nic = netdev_priv(netdev);
-       struct net_device *pnetdev = nic->pnicvf->netdev;
+       struct nicvf *nic;
+       struct net_device *pnetdev;
+
+       if (!netdev)
+               return;
+
+       nic = netdev_priv(netdev);
+       pnetdev = nic->pnicvf->netdev;
 
        /* Check if this Qset is assigned to different VF.
         * If yes, clean primary and all secondary Qsets.
index f6e858d0b9d421a54bdf7b1bf294b2dd77c3cc55..ebdc83247bb6af1c841d62513978ce21d59f0d92 100644 (file)
@@ -17,15 +17,16 @@ config NET_VENDOR_DLINK
 if NET_VENDOR_DLINK
 
 config DL2K
-       tristate "DL2000/TC902x-based Gigabit Ethernet support"
+       tristate "DL2000/TC902x/IP1000A-based Gigabit Ethernet support"
        depends on PCI
        select CRC32
        ---help---
-         This driver supports DL2000/TC902x-based Gigabit ethernet cards,
+         This driver supports DL2000/TC902x/IP1000A-based Gigabit ethernet cards,
          which includes
          D-Link DGE-550T Gigabit Ethernet Adapter.
          D-Link DL2000-based Gigabit Ethernet Adapter.
          Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
+         ICPlus IP1000A-based cards
 
          To compile this driver as a module, choose M here: the
          module will be called dl2k.
index cf0a5fcdaaaf06e59772d5b4530547e11c7b4819..ccca4799c27b83cf191fc80f3d72a21328f8708e 100644 (file)
@@ -253,6 +253,19 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto err_out_unmap_rx;
 
+       if (np->chip_id == CHIP_IP1000A &&
+           (np->pdev->revision == 0x40 || np->pdev->revision == 0x41)) {
+               /* PHY magic taken from ipg driver, undocumented registers */
+               mii_write(dev, np->phy_addr, 31, 0x0001);
+               mii_write(dev, np->phy_addr, 27, 0x01e0);
+               mii_write(dev, np->phy_addr, 31, 0x0002);
+               mii_write(dev, np->phy_addr, 27, 0xeb8e);
+               mii_write(dev, np->phy_addr, 31, 0x0000);
+               mii_write(dev, np->phy_addr, 30, 0x005e);
+               /* advertise 1000BASE-T half & full duplex, prefer MASTER */
+               mii_write(dev, np->phy_addr, MII_CTRL1000, 0x0700);
+       }
+
        /* Fiber device? */
        np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0;
        np->link_status = 0;
@@ -361,6 +374,11 @@ parse_eeprom (struct net_device *dev)
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = psrom->mac_addr[i];
 
+       if (np->chip_id == CHIP_IP1000A) {
+               np->led_mode = psrom->led_mode;
+               return 0;
+       }
+
        if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) {
                return 0;
        }
@@ -406,6 +424,28 @@ parse_eeprom (struct net_device *dev)
        return 0;
 }
 
+static void rio_set_led_mode(struct net_device *dev)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->ioaddr;
+       u32 mode;
+
+       if (np->chip_id != CHIP_IP1000A)
+               return;
+
+       mode = dr32(ASICCtrl);
+       mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED);
+
+       if (np->led_mode & 0x01)
+               mode |= IPG_AC_LED_MODE;
+       if (np->led_mode & 0x02)
+               mode |= IPG_AC_LED_MODE_BIT_1;
+       if (np->led_mode & 0x08)
+               mode |= IPG_AC_LED_SPEED;
+
+       dw32(ASICCtrl, mode);
+}
+
 static int
 rio_open (struct net_device *dev)
 {
@@ -424,6 +464,8 @@ rio_open (struct net_device *dev)
             GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset);
        mdelay(10);
 
+       rio_set_led_mode(dev);
+
        /* DebugCtrl bit 4, 5, 9 must set */
        dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230);
 
@@ -433,9 +475,13 @@ rio_open (struct net_device *dev)
 
        alloc_list (dev);
 
-       /* Get station address */
-       for (i = 0; i < 6; i++)
-               dw8(StationAddr0 + i, dev->dev_addr[i]);
+       /* Set station address */
+       /* 16 or 32-bit access is required by TC9020 datasheet but 8-bit works
+        * too. However, it doesn't work on IP1000A so we use 16-bit access.
+        */
+       for (i = 0; i < 3; i++)
+               dw16(StationAddr0 + 2 * i,
+                    cpu_to_le16(((u16 *)dev->dev_addr)[i]));
 
        set_multicast (dev);
        if (np->coalesce) {
@@ -780,6 +826,7 @@ tx_error (struct net_device *dev, int tx_status)
                                break;
                        mdelay (1);
                }
+               rio_set_led_mode(dev);
                rio_free_tx (dev, 1);
                /* Reset TFDListPtr */
                dw32(TFDListPtr0, np->tx_ring_dma +
@@ -799,6 +846,7 @@ tx_error (struct net_device *dev, int tx_status)
                                break;
                        mdelay (1);
                }
+               rio_set_led_mode(dev);
                /* Let TxStartThresh stay default value */
        }
        /* Maximum Collisions */
@@ -965,6 +1013,7 @@ rio_error (struct net_device *dev, int int_status)
                        dev->name, int_status);
                dw16(ASICCtrl + 2, GlobalReset | HostReset);
                mdelay (500);
+               rio_set_led_mode(dev);
        }
 }
 
index 23c07b0070696da9c41726aba73f01e338a4ca2e..8f4f61262d5cb7be21d994d7ffb411a654ae589b 100644 (file)
@@ -211,6 +211,10 @@ enum ASICCtrl_HiWord_bits {
        ResetBusy = 0x0400,
 };
 
+#define IPG_AC_LED_MODE                BIT(14)
+#define IPG_AC_LED_SPEED       BIT(27)
+#define IPG_AC_LED_MODE_BIT_1  BIT(29)
+
 /* Transmit Frame Control bits */
 enum TFC_bits {
        DwordAlign = 0x00000000,
@@ -332,7 +336,10 @@ typedef struct t_SROM {
        u16 asic_ctrl;          /* 0x02 */
        u16 sub_vendor_id;      /* 0x04 */
        u16 sub_system_id;      /* 0x06 */
-       u16 reserved1[12];      /* 0x08-0x1f */
+       u16 pci_base_1;         /* 0x08 (IP1000A only) */
+       u16 pci_base_2;         /* 0x0a (IP1000A only) */
+       u16 led_mode;           /* 0x0c (IP1000A only) */
+       u16 reserved1[9];       /* 0x0e-0x1f */
        u8 mac_addr[6];         /* 0x20-0x25 */
        u8 reserved2[10];       /* 0x26-0x2f */
        u8 sib[204];            /* 0x30-0xfb */
@@ -397,6 +404,7 @@ struct netdev_private {
        u16 advertising;        /* NWay media advertisement */
        u16 negotiate;          /* Negotiated media */
        int phy_addr;           /* PHY addresses. */
+       u16 led_mode;           /* LED mode read from EEPROM (IP1000A only) */
 };
 
 /* The station address location in the EEPROM. */
@@ -407,10 +415,15 @@ struct netdev_private {
         class_mask              of the class are honored during the comparison.
         driver_data             Data private to the driver.
 */
+#define CHIP_IP1000A   1
 
 static const struct pci_device_id rio_pci_tbl[] = {
        {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
        {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VDEVICE(SUNDANCE, 0x1023), CHIP_IP1000A },
+       { PCI_VDEVICE(SUNDANCE, 0x2021), CHIP_IP1000A },
+       { PCI_VDEVICE(DLINK,    0x9021), CHIP_IP1000A },
+       { PCI_VDEVICE(DLINK,    0x4020), CHIP_IP1000A },
        { }
 };
 MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
index f4cb8e425853a3fd85151d3b6df5e7651b95f81a..734f655c99c113805e270a0846e934553fbca9b7 100644 (file)
@@ -1062,9 +1062,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
 static int be_set_rss_hash_opts(struct be_adapter *adapter,
                                struct ethtool_rxnfc *cmd)
 {
-       struct be_rx_obj *rxo;
-       int status = 0, i, j;
-       u8 rsstable[128];
+       int status;
        u32 rss_flags = adapter->rss_info.rss_flags;
 
        if (cmd->data != L3_RSS_FLAGS &&
@@ -1113,20 +1111,11 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter,
        }
 
        if (rss_flags == adapter->rss_info.rss_flags)
-               return status;
-
-       if (be_multi_rxq(adapter)) {
-               for (j = 0; j < 128; j += adapter->num_rss_qs) {
-                       for_all_rss_queues(adapter, rxo, i) {
-                               if ((j + i) >= 128)
-                                       break;
-                               rsstable[j + i] = rxo->rss_id;
-                       }
-               }
-       }
+               return 0;
 
        status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable,
-                                  rss_flags, 128, adapter->rss_info.rss_hkey);
+                                  rss_flags, RSS_INDIR_TABLE_LEN,
+                                  adapter->rss_info.rss_hkey);
        if (!status)
                adapter->rss_info.rss_flags = rss_flags;
 
index eb48a977f8daabe78d6d5b6a94f6607bf19287b8..b6ad02909d6b3c87b861d4e35c345426bef30a64 100644 (file)
@@ -3518,7 +3518,7 @@ static int be_rx_qs_create(struct be_adapter *adapter)
 
        netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN);
        rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags,
-                              128, rss_key);
+                              RSS_INDIR_TABLE_LEN, rss_key);
        if (rc) {
                rss->rss_flags = RSS_ENABLE_NONE;
                return rc;
diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig
deleted file mode 100644 (file)
index 14a66e9..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# IC Plus device configuration
-#
-
-config IP1000
-       tristate "IP1000 Gigabit Ethernet support"
-       depends on PCI
-       select MII
-       ---help---
-         This driver supports IP1000 gigabit Ethernet cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called ipg.  This is recommended.
diff --git a/drivers/net/ethernet/icplus/Makefile b/drivers/net/ethernet/icplus/Makefile
deleted file mode 100644 (file)
index 5bc87c1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the IC Plus device drivers
-#
-
-obj-$(CONFIG_IP1000) += ipg.o
diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c
deleted file mode 100644 (file)
index c3b6af8..0000000
+++ /dev/null
@@ -1,2300 +0,0 @@
-/*
- * ipg.c: Device Driver for the IP1000 Gigabit Ethernet Adapter
- *
- * Copyright (C) 2003, 2007  IC Plus Corp
- *
- * Original Author:
- *
- *   Craig Rich
- *   Sundance Technology, Inc.
- *   www.sundanceti.com
- *   craig_rich@sundanceti.com
- *
- * Current Maintainer:
- *
- *   Sorbica Shieh.
- *   http://www.icplus.com.tw
- *   sorbica@icplus.com.tw
- *
- *   Jesse Huang
- *   http://www.icplus.com.tw
- *   jesse@icplus.com.tw
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/interrupt.h>
-#include <linux/gfp.h>
-#include <linux/mii.h>
-#include <linux/mutex.h>
-
-#include <asm/div64.h>
-
-#define IPG_RX_RING_BYTES      (sizeof(struct ipg_rx) * IPG_RFDLIST_LENGTH)
-#define IPG_TX_RING_BYTES      (sizeof(struct ipg_tx) * IPG_TFDLIST_LENGTH)
-#define IPG_RESET_MASK \
-       (IPG_AC_GLOBAL_RESET | IPG_AC_RX_RESET | IPG_AC_TX_RESET | \
-        IPG_AC_DMA | IPG_AC_FIFO | IPG_AC_NETWORK | IPG_AC_HOST | \
-        IPG_AC_AUTO_INIT)
-
-#define ipg_w32(val32, reg)    iowrite32((val32), ioaddr + (reg))
-#define ipg_w16(val16, reg)    iowrite16((val16), ioaddr + (reg))
-#define ipg_w8(val8, reg)      iowrite8((val8), ioaddr + (reg))
-
-#define ipg_r32(reg)           ioread32(ioaddr + (reg))
-#define ipg_r16(reg)           ioread16(ioaddr + (reg))
-#define ipg_r8(reg)            ioread8(ioaddr + (reg))
-
-enum {
-       netdev_io_size = 128
-};
-
-#include "ipg.h"
-#define DRV_NAME       "ipg"
-
-MODULE_AUTHOR("IC Plus Corp. 2003");
-MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Defaults
- */
-#define IPG_MAX_RXFRAME_SIZE   0x0600
-#define IPG_RXFRAG_SIZE                0x0600
-#define IPG_RXSUPPORT_SIZE     0x0600
-#define IPG_IS_JUMBO           false
-
-/*
- * Variable record -- index by leading revision/length
- * Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN
- */
-static const unsigned short DefaultPhyParam[] = {
-       /* 11/12/03 IP1000A v1-3 rev=0x40 */
-       /*--------------------------------------------------------------------------
-       (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2,
-                                27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6,
-                                31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7,  9, 0x0700,
-         --------------------------------------------------------------------------*/
-       /* 12/17/03 IP1000A v1-4 rev=0x40 */
-       (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
-           0x0000,
-       30, 0x005e, 9, 0x0700,
-       /* 01/09/04 IP1000A v1-5 rev=0x41 */
-       (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31,
-           0x0000,
-       30, 0x005e, 9, 0x0700,
-       0x0000
-};
-
-static const char * const ipg_brand_name[] = {
-       "IC PLUS IP1000 1000/100/10 based NIC",
-       "Sundance Technology ST2021 based NIC",
-       "Tamarack Microelectronics TC9020/9021 based NIC",
-       "D-Link NIC IP1000A"
-};
-
-static const struct pci_device_id ipg_pci_tbl[] = {
-       { PCI_VDEVICE(SUNDANCE, 0x1023), 0 },
-       { PCI_VDEVICE(SUNDANCE, 0x2021), 1 },
-       { PCI_VDEVICE(DLINK,    0x9021), 2 },
-       { PCI_VDEVICE(DLINK,    0x4020), 3 },
-       { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, ipg_pci_tbl);
-
-static inline void __iomem *ipg_ioaddr(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       return sp->ioaddr;
-}
-
-#ifdef IPG_DEBUG
-static void ipg_dump_rfdlist(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-       u32 offset;
-
-       IPG_DEBUG_MSG("_dump_rfdlist\n");
-
-       netdev_info(dev, "rx_current = %02x\n", sp->rx_current);
-       netdev_info(dev, "rx_dirty   = %02x\n", sp->rx_dirty);
-       netdev_info(dev, "RFDList start address = %016lx\n",
-                   (unsigned long)sp->rxd_map);
-       netdev_info(dev, "RFDListPtr register   = %08x%08x\n",
-                   ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0));
-
-       for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
-               offset = (u32) &sp->rxd[i].next_desc - (u32) sp->rxd;
-               netdev_info(dev, "%02x %04x RFDNextPtr = %016lx\n",
-                           i, offset, (unsigned long)sp->rxd[i].next_desc);
-               offset = (u32) &sp->rxd[i].rfs - (u32) sp->rxd;
-               netdev_info(dev, "%02x %04x RFS        = %016lx\n",
-                           i, offset, (unsigned long)sp->rxd[i].rfs);
-               offset = (u32) &sp->rxd[i].frag_info - (u32) sp->rxd;
-               netdev_info(dev, "%02x %04x frag_info   = %016lx\n",
-                           i, offset, (unsigned long)sp->rxd[i].frag_info);
-       }
-}
-
-static void ipg_dump_tfdlist(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-       u32 offset;
-
-       IPG_DEBUG_MSG("_dump_tfdlist\n");
-
-       netdev_info(dev, "tx_current         = %02x\n", sp->tx_current);
-       netdev_info(dev, "tx_dirty = %02x\n", sp->tx_dirty);
-       netdev_info(dev, "TFDList start address = %016lx\n",
-                   (unsigned long) sp->txd_map);
-       netdev_info(dev, "TFDListPtr register   = %08x%08x\n",
-                   ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0));
-
-       for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
-               offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd;
-               netdev_info(dev, "%02x %04x TFDNextPtr = %016lx\n",
-                           i, offset, (unsigned long)sp->txd[i].next_desc);
-
-               offset = (u32) &sp->txd[i].tfc - (u32) sp->txd;
-               netdev_info(dev, "%02x %04x TFC        = %016lx\n",
-                           i, offset, (unsigned long) sp->txd[i].tfc);
-               offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd;
-               netdev_info(dev, "%02x %04x frag_info   = %016lx\n",
-                           i, offset, (unsigned long) sp->txd[i].frag_info);
-       }
-}
-#endif
-
-static void ipg_write_phy_ctl(void __iomem *ioaddr, u8 data)
-{
-       ipg_w8(IPG_PC_RSVD_MASK & data, PHY_CTRL);
-       ndelay(IPG_PC_PHYCTRLWAIT_NS);
-}
-
-static void ipg_drive_phy_ctl_low_high(void __iomem *ioaddr, u8 data)
-{
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | data);
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | data);
-}
-
-static void send_three_state(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
-       phyctrlpolarity |= (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR;
-
-       ipg_drive_phy_ctl_low_high(ioaddr, phyctrlpolarity);
-}
-
-static void send_end(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
-       ipg_w8((IPG_PC_MGMTCLK_LO | (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR |
-               phyctrlpolarity) & IPG_PC_RSVD_MASK, PHY_CTRL);
-}
-
-static u16 read_phy_bit(void __iomem *ioaddr, u8 phyctrlpolarity)
-{
-       u16 bit_data;
-
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | phyctrlpolarity);
-
-       bit_data = ((ipg_r8(PHY_CTRL) & IPG_PC_MGMTDATA) >> 1) & 1;
-
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | phyctrlpolarity);
-
-       return bit_data;
-}
-
-/*
- * Read a register from the Physical Layer device located
- * on the IPG NIC, using the IPG PHYCTRL register.
- */
-static int mdio_read(struct net_device *dev, int phy_id, int phy_reg)
-{
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       /*
-        * The GMII mangement frame structure for a read is as follows:
-        *
-        * |Preamble|st|op|phyad|regad|ta|      data      |idle|
-        * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z   |
-        *
-        * <32 1s> = 32 consecutive logic 1 values
-        * A = bit of Physical Layer device address (MSB first)
-        * R = bit of register address (MSB first)
-        * z = High impedance state
-        * D = bit of read data (MSB first)
-        *
-        * Transmission order is 'Preamble' field first, bits transmitted
-        * left to right (first to last).
-        */
-       struct {
-               u32 field;
-               unsigned int len;
-       } p[] = {
-               { GMII_PREAMBLE,        32 },   /* Preamble */
-               { GMII_ST,              2  },   /* ST */
-               { GMII_READ,            2  },   /* OP */
-               { phy_id,               5  },   /* PHYAD */
-               { phy_reg,              5  },   /* REGAD */
-               { 0x0000,               2  },   /* TA */
-               { 0x0000,               16 },   /* DATA */
-               { 0x0000,               1  }    /* IDLE */
-       };
-       unsigned int i, j;
-       u8 polarity, data;
-
-       polarity  = ipg_r8(PHY_CTRL);
-       polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
-       /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
-       for (j = 0; j < 5; j++) {
-               for (i = 0; i < p[j].len; i++) {
-                       /* For each variable length field, the MSB must be
-                        * transmitted first. Rotate through the field bits,
-                        * starting with the MSB, and move each bit into the
-                        * the 1st (2^1) bit position (this is the bit position
-                        * corresponding to the MgmtData bit of the PhyCtrl
-                        * register for the IPG).
-                        *
-                        * Example: ST = 01;
-                        *
-                        *          First write a '0' to bit 1 of the PhyCtrl
-                        *          register, then write a '1' to bit 1 of the
-                        *          PhyCtrl register.
-                        *
-                        * To do this, right shift the MSB of ST by the value:
-                        * [field length - 1 - #ST bits already written]
-                        * then left shift this result by 1.
-                        */
-                       data  = (p[j].field >> (p[j].len - 1 - i)) << 1;
-                       data &= IPG_PC_MGMTDATA;
-                       data |= polarity | IPG_PC_MGMTDIR;
-
-                       ipg_drive_phy_ctl_low_high(ioaddr, data);
-               }
-       }
-
-       send_three_state(ioaddr, polarity);
-
-       read_phy_bit(ioaddr, polarity);
-
-       /*
-        * For a read cycle, the bits for the next two fields (TA and
-        * DATA) are driven by the PHY (the IPG reads these bits).
-        */
-       for (i = 0; i < p[6].len; i++) {
-               p[6].field |=
-                   (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i));
-       }
-
-       send_three_state(ioaddr, polarity);
-       send_three_state(ioaddr, polarity);
-       send_three_state(ioaddr, polarity);
-       send_end(ioaddr, polarity);
-
-       /* Return the value of the DATA field. */
-       return p[6].field;
-}
-
-/*
- * Write to a register from the Physical Layer device located
- * on the IPG NIC, using the IPG PHYCTRL register.
- */
-static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val)
-{
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       /*
-        * The GMII mangement frame structure for a read is as follows:
-        *
-        * |Preamble|st|op|phyad|regad|ta|      data      |idle|
-        * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z   |
-        *
-        * <32 1s> = 32 consecutive logic 1 values
-        * A = bit of Physical Layer device address (MSB first)
-        * R = bit of register address (MSB first)
-        * z = High impedance state
-        * D = bit of write data (MSB first)
-        *
-        * Transmission order is 'Preamble' field first, bits transmitted
-        * left to right (first to last).
-        */
-       struct {
-               u32 field;
-               unsigned int len;
-       } p[] = {
-               { GMII_PREAMBLE,        32 },   /* Preamble */
-               { GMII_ST,              2  },   /* ST */
-               { GMII_WRITE,           2  },   /* OP */
-               { phy_id,               5  },   /* PHYAD */
-               { phy_reg,              5  },   /* REGAD */
-               { 0x0002,               2  },   /* TA */
-               { val & 0xffff,         16 },   /* DATA */
-               { 0x0000,               1  }    /* IDLE */
-       };
-       unsigned int i, j;
-       u8 polarity, data;
-
-       polarity  = ipg_r8(PHY_CTRL);
-       polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY);
-
-       /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */
-       for (j = 0; j < 7; j++) {
-               for (i = 0; i < p[j].len; i++) {
-                       /* For each variable length field, the MSB must be
-                        * transmitted first. Rotate through the field bits,
-                        * starting with the MSB, and move each bit into the
-                        * the 1st (2^1) bit position (this is the bit position
-                        * corresponding to the MgmtData bit of the PhyCtrl
-                        * register for the IPG).
-                        *
-                        * Example: ST = 01;
-                        *
-                        *          First write a '0' to bit 1 of the PhyCtrl
-                        *          register, then write a '1' to bit 1 of the
-                        *          PhyCtrl register.
-                        *
-                        * To do this, right shift the MSB of ST by the value:
-                        * [field length - 1 - #ST bits already written]
-                        * then left shift this result by 1.
-                        */
-                       data  = (p[j].field >> (p[j].len - 1 - i)) << 1;
-                       data &= IPG_PC_MGMTDATA;
-                       data |= polarity | IPG_PC_MGMTDIR;
-
-                       ipg_drive_phy_ctl_low_high(ioaddr, data);
-               }
-       }
-
-       /* The last cycle is a tri-state, so read from the PHY. */
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity);
-       ipg_r8(PHY_CTRL);
-       ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity);
-}
-
-static void ipg_set_led_mode(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       u32 mode;
-
-       mode = ipg_r32(ASIC_CTRL);
-       mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED);
-
-       if ((sp->led_mode & 0x03) > 1)
-               mode |= IPG_AC_LED_MODE_BIT_1;  /* Write Asic Control Bit 29 */
-
-       if ((sp->led_mode & 0x01) == 1)
-               mode |= IPG_AC_LED_MODE;        /* Write Asic Control Bit 14 */
-
-       if ((sp->led_mode & 0x08) == 8)
-               mode |= IPG_AC_LED_SPEED;       /* Write Asic Control Bit 27 */
-
-       ipg_w32(mode, ASIC_CTRL);
-}
-
-static void ipg_set_phy_set(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       int physet;
-
-       physet = ipg_r8(PHY_SET);
-       physet &= ~(IPG_PS_MEM_LENB9B | IPG_PS_MEM_LEN9 | IPG_PS_NON_COMPDET);
-       physet |= ((sp->led_mode & 0x70) >> 4);
-       ipg_w8(physet, PHY_SET);
-}
-
-static int ipg_reset(struct net_device *dev, u32 resetflags)
-{
-       /* Assert functional resets via the IPG AsicCtrl
-        * register as specified by the 'resetflags' input
-        * parameter.
-        */
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       unsigned int timeout_count = 0;
-
-       IPG_DEBUG_MSG("_reset\n");
-
-       ipg_w32(ipg_r32(ASIC_CTRL) | resetflags, ASIC_CTRL);
-
-       /* Delay added to account for problem with 10Mbps reset. */
-       mdelay(IPG_AC_RESETWAIT);
-
-       while (IPG_AC_RESET_BUSY & ipg_r32(ASIC_CTRL)) {
-               mdelay(IPG_AC_RESETWAIT);
-               if (++timeout_count > IPG_AC_RESET_TIMEOUT)
-                       return -ETIME;
-       }
-       /* Set LED Mode in Asic Control */
-       ipg_set_led_mode(dev);
-
-       /* Set PHYSet Register Value */
-       ipg_set_phy_set(dev);
-       return 0;
-}
-
-/* Find the GMII PHY address. */
-static int ipg_find_phyaddr(struct net_device *dev)
-{
-       unsigned int phyaddr, i;
-
-       for (i = 0; i < 32; i++) {
-               u32 status;
-
-               /* Search for the correct PHY address among 32 possible. */
-               phyaddr = (IPG_NIC_PHY_ADDRESS + i) % 32;
-
-               /* 10/22/03 Grace change verify from GMII_PHY_STATUS to
-                  GMII_PHY_ID1
-                */
-
-               status = mdio_read(dev, phyaddr, MII_BMSR);
-
-               if ((status != 0xFFFF) && (status != 0))
-                       return phyaddr;
-       }
-
-       return 0x1f;
-}
-
-/*
- * Configure IPG based on result of IEEE 802.3 PHY
- * auto-negotiation.
- */
-static int ipg_config_autoneg(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int txflowcontrol;
-       unsigned int rxflowcontrol;
-       unsigned int fullduplex;
-       u32 mac_ctrl_val;
-       u32 asicctrl;
-       u8 phyctrl;
-       const char *speed;
-       const char *duplex;
-       const char *tx_desc;
-       const char *rx_desc;
-
-       IPG_DEBUG_MSG("_config_autoneg\n");
-
-       asicctrl = ipg_r32(ASIC_CTRL);
-       phyctrl = ipg_r8(PHY_CTRL);
-       mac_ctrl_val = ipg_r32(MAC_CTRL);
-
-       /* Set flags for use in resolving auto-negotiation, assuming
-        * non-1000Mbps, half duplex, no flow control.
-        */
-       fullduplex = 0;
-       txflowcontrol = 0;
-       rxflowcontrol = 0;
-
-       /* To accommodate a problem in 10Mbps operation,
-        * set a global flag if PHY running in 10Mbps mode.
-        */
-       sp->tenmbpsmode = 0;
-
-       /* Determine actual speed of operation. */
-       switch (phyctrl & IPG_PC_LINK_SPEED) {
-       case IPG_PC_LINK_SPEED_10MBPS:
-               speed = "10Mbps";
-               sp->tenmbpsmode = 1;
-               break;
-       case IPG_PC_LINK_SPEED_100MBPS:
-               speed = "100Mbps";
-               break;
-       case IPG_PC_LINK_SPEED_1000MBPS:
-               speed = "1000Mbps";
-               break;
-       default:
-               speed = "undefined!";
-               return 0;
-       }
-
-       netdev_info(dev, "Link speed = %s\n", speed);
-       if (sp->tenmbpsmode == 1)
-               netdev_info(dev, "10Mbps operational mode enabled\n");
-
-       if (phyctrl & IPG_PC_DUPLEX_STATUS) {
-               fullduplex = 1;
-               txflowcontrol = 1;
-               rxflowcontrol = 1;
-       }
-
-       /* Configure full duplex, and flow control. */
-       if (fullduplex == 1) {
-
-               /* Configure IPG for full duplex operation. */
-
-               duplex = "full";
-
-               mac_ctrl_val |= IPG_MC_DUPLEX_SELECT_FD;
-
-               if (txflowcontrol == 1) {
-                       tx_desc  = "";
-                       mac_ctrl_val |= IPG_MC_TX_FLOW_CONTROL_ENABLE;
-               } else {
-                       tx_desc = "no ";
-                       mac_ctrl_val &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE;
-               }
-
-               if (rxflowcontrol == 1) {
-                       rx_desc = "";
-                       mac_ctrl_val |= IPG_MC_RX_FLOW_CONTROL_ENABLE;
-               } else {
-                       rx_desc = "no ";
-                       mac_ctrl_val &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE;
-               }
-       } else {
-               duplex = "half";
-               tx_desc = "no ";
-               rx_desc = "no ";
-               mac_ctrl_val &= (~IPG_MC_DUPLEX_SELECT_FD &
-                                ~IPG_MC_TX_FLOW_CONTROL_ENABLE &
-                                ~IPG_MC_RX_FLOW_CONTROL_ENABLE);
-       }
-
-       netdev_info(dev, "setting %s duplex, %sTX, %sRX flow control\n",
-                   duplex, tx_desc, rx_desc);
-       ipg_w32(mac_ctrl_val, MAC_CTRL);
-
-       return 0;
-}
-
-/* Determine and configure multicast operation and set
- * receive mode for IPG.
- */
-static void ipg_nic_set_multicast_list(struct net_device *dev)
-{
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       struct netdev_hw_addr *ha;
-       unsigned int hashindex;
-       u32 hashtable[2];
-       u8 receivemode;
-
-       IPG_DEBUG_MSG("_nic_set_multicast_list\n");
-
-       receivemode = IPG_RM_RECEIVEUNICAST | IPG_RM_RECEIVEBROADCAST;
-
-       if (dev->flags & IFF_PROMISC) {
-               /* NIC to be configured in promiscuous mode. */
-               receivemode = IPG_RM_RECEIVEALLFRAMES;
-       } else if ((dev->flags & IFF_ALLMULTI) ||
-                  ((dev->flags & IFF_MULTICAST) &&
-                   (netdev_mc_count(dev) > IPG_MULTICAST_HASHTABLE_SIZE))) {
-               /* NIC to be configured to receive all multicast
-                * frames. */
-               receivemode |= IPG_RM_RECEIVEMULTICAST;
-       } else if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) {
-               /* NIC to be configured to receive selected
-                * multicast addresses. */
-               receivemode |= IPG_RM_RECEIVEMULTICASTHASH;
-       }
-
-       /* Calculate the bits to set for the 64 bit, IPG HASHTABLE.
-        * The IPG applies a cyclic-redundancy-check (the same CRC
-        * used to calculate the frame data FCS) to the destination
-        * address all incoming multicast frames whose destination
-        * address has the multicast bit set. The least significant
-        * 6 bits of the CRC result are used as an addressing index
-        * into the hash table. If the value of the bit addressed by
-        * this index is a 1, the frame is passed to the host system.
-        */
-
-       /* Clear hashtable. */
-       hashtable[0] = 0x00000000;
-       hashtable[1] = 0x00000000;
-
-       /* Cycle through all multicast addresses to filter. */
-       netdev_for_each_mc_addr(ha, dev) {
-               /* Calculate CRC result for each multicast address. */
-               hashindex = crc32_le(0xffffffff, ha->addr,
-                                    ETH_ALEN);
-
-               /* Use only the least significant 6 bits. */
-               hashindex = hashindex & 0x3F;
-
-               /* Within "hashtable", set bit number "hashindex"
-                * to a logic 1.
-                */
-               set_bit(hashindex, (void *)hashtable);
-       }
-
-       /* Write the value of the hashtable, to the 4, 16 bit
-        * HASHTABLE IPG registers.
-        */
-       ipg_w32(hashtable[0], HASHTABLE_0);
-       ipg_w32(hashtable[1], HASHTABLE_1);
-
-       ipg_w8(IPG_RM_RSVD_MASK & receivemode, RECEIVE_MODE);
-
-       IPG_DEBUG_MSG("ReceiveMode = %x\n", ipg_r8(RECEIVE_MODE));
-}
-
-static int ipg_io_config(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       u32 origmacctrl;
-       u32 restoremacctrl;
-
-       IPG_DEBUG_MSG("_io_config\n");
-
-       origmacctrl = ipg_r32(MAC_CTRL);
-
-       restoremacctrl = origmacctrl | IPG_MC_STATISTICS_ENABLE;
-
-       /* Based on compilation option, determine if FCS is to be
-        * stripped on receive frames by IPG.
-        */
-       if (!IPG_STRIP_FCS_ON_RX)
-               restoremacctrl |= IPG_MC_RCV_FCS;
-
-       /* Determine if transmitter and/or receiver are
-        * enabled so we may restore MACCTRL correctly.
-        */
-       if (origmacctrl & IPG_MC_TX_ENABLED)
-               restoremacctrl |= IPG_MC_TX_ENABLE;
-
-       if (origmacctrl & IPG_MC_RX_ENABLED)
-               restoremacctrl |= IPG_MC_RX_ENABLE;
-
-       /* Transmitter and receiver must be disabled before setting
-        * IFSSelect.
-        */
-       ipg_w32((origmacctrl & (IPG_MC_RX_DISABLE | IPG_MC_TX_DISABLE)) &
-               IPG_MC_RSVD_MASK, MAC_CTRL);
-
-       /* Now that transmitter and receiver are disabled, write
-        * to IFSSelect.
-        */
-       ipg_w32((origmacctrl & IPG_MC_IFS_96BIT) & IPG_MC_RSVD_MASK, MAC_CTRL);
-
-       /* Set RECEIVEMODE register. */
-       ipg_nic_set_multicast_list(dev);
-
-       ipg_w16(sp->max_rxframe_size, MAX_FRAME_SIZE);
-
-       ipg_w8(IPG_RXDMAPOLLPERIOD_VALUE,   RX_DMA_POLL_PERIOD);
-       ipg_w8(IPG_RXDMAURGENTTHRESH_VALUE, RX_DMA_URGENT_THRESH);
-       ipg_w8(IPG_RXDMABURSTTHRESH_VALUE,  RX_DMA_BURST_THRESH);
-       ipg_w8(IPG_TXDMAPOLLPERIOD_VALUE,   TX_DMA_POLL_PERIOD);
-       ipg_w8(IPG_TXDMAURGENTTHRESH_VALUE, TX_DMA_URGENT_THRESH);
-       ipg_w8(IPG_TXDMABURSTTHRESH_VALUE,  TX_DMA_BURST_THRESH);
-       ipg_w16((IPG_IE_HOST_ERROR | IPG_IE_TX_DMA_COMPLETE |
-                IPG_IE_TX_COMPLETE | IPG_IE_INT_REQUESTED |
-                IPG_IE_UPDATE_STATS | IPG_IE_LINK_EVENT |
-                IPG_IE_RX_DMA_COMPLETE | IPG_IE_RX_DMA_PRIORITY), INT_ENABLE);
-       ipg_w16(IPG_FLOWONTHRESH_VALUE,  FLOW_ON_THRESH);
-       ipg_w16(IPG_FLOWOFFTHRESH_VALUE, FLOW_OFF_THRESH);
-
-       /* IPG multi-frag frame bug workaround.
-        * Per silicon revision B3 eratta.
-        */
-       ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0200, DEBUG_CTRL);
-
-       /* IPG TX poll now bug workaround.
-        * Per silicon revision B3 eratta.
-        */
-       ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0010, DEBUG_CTRL);
-
-       /* IPG RX poll now bug workaround.
-        * Per silicon revision B3 eratta.
-        */
-       ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0020, DEBUG_CTRL);
-
-       /* Now restore MACCTRL to original setting. */
-       ipg_w32(IPG_MC_RSVD_MASK & restoremacctrl, MAC_CTRL);
-
-       /* Disable unused RMON statistics. */
-       ipg_w32(IPG_RZ_ALL, RMON_STATISTICS_MASK);
-
-       /* Disable unused MIB statistics. */
-       ipg_w32(IPG_SM_MACCONTROLFRAMESXMTD | IPG_SM_MACCONTROLFRAMESRCVD |
-               IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK | IPG_SM_TXJUMBOFRAMES |
-               IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK | IPG_SM_RXJUMBOFRAMES |
-               IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK |
-               IPG_SM_UDPCHECKSUMERRORS | IPG_SM_TCPCHECKSUMERRORS |
-               IPG_SM_IPCHECKSUMERRORS, STATISTICS_MASK);
-
-       return 0;
-}
-
-/*
- * Create a receive buffer within system memory and update
- * NIC private structure appropriately.
- */
-static int ipg_get_rxbuff(struct net_device *dev, int entry)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       struct ipg_rx *rxfd = sp->rxd + entry;
-       struct sk_buff *skb;
-       u64 rxfragsize;
-
-       IPG_DEBUG_MSG("_get_rxbuff\n");
-
-       skb = netdev_alloc_skb_ip_align(dev, sp->rxsupport_size);
-       if (!skb) {
-               sp->rx_buff[entry] = NULL;
-               return -ENOMEM;
-       }
-
-       /* Save the address of the sk_buff structure. */
-       sp->rx_buff[entry] = skb;
-
-       rxfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data,
-               sp->rx_buf_sz, PCI_DMA_FROMDEVICE));
-
-       /* Set the RFD fragment length. */
-       rxfragsize = sp->rxfrag_size;
-       rxfd->frag_info |= cpu_to_le64((rxfragsize << 48) & IPG_RFI_FRAGLEN);
-
-       return 0;
-}
-
-static int init_rfdlist(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-
-       IPG_DEBUG_MSG("_init_rfdlist\n");
-
-       for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
-               struct ipg_rx *rxfd = sp->rxd + i;
-
-               if (sp->rx_buff[i]) {
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                               sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb_irq(sp->rx_buff[i]);
-                       sp->rx_buff[i] = NULL;
-               }
-
-               /* Clear out the RFS field. */
-               rxfd->rfs = 0x0000000000000000;
-
-               if (ipg_get_rxbuff(dev, i) < 0) {
-                       /*
-                        * A receive buffer was not ready, break the
-                        * RFD list here.
-                        */
-                       IPG_DEBUG_MSG("Cannot allocate Rx buffer\n");
-
-                       /* Just in case we cannot allocate a single RFD.
-                        * Should not occur.
-                        */
-                       if (i == 0) {
-                               netdev_err(dev, "No memory available for RFD list\n");
-                               return -ENOMEM;
-                       }
-               }
-
-               rxfd->next_desc = cpu_to_le64(sp->rxd_map +
-                       sizeof(struct ipg_rx)*(i + 1));
-       }
-       sp->rxd[i - 1].next_desc = cpu_to_le64(sp->rxd_map);
-
-       sp->rx_current = 0;
-       sp->rx_dirty = 0;
-
-       /* Write the location of the RFDList to the IPG. */
-       ipg_w32((u32) sp->rxd_map, RFD_LIST_PTR_0);
-       ipg_w32(0x00000000, RFD_LIST_PTR_1);
-
-       return 0;
-}
-
-static void init_tfdlist(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-
-       IPG_DEBUG_MSG("_init_tfdlist\n");
-
-       for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
-               struct ipg_tx *txfd = sp->txd + i;
-
-               txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE);
-
-               if (sp->tx_buff[i]) {
-                       dev_kfree_skb_irq(sp->tx_buff[i]);
-                       sp->tx_buff[i] = NULL;
-               }
-
-               txfd->next_desc = cpu_to_le64(sp->txd_map +
-                       sizeof(struct ipg_tx)*(i + 1));
-       }
-       sp->txd[i - 1].next_desc = cpu_to_le64(sp->txd_map);
-
-       sp->tx_current = 0;
-       sp->tx_dirty = 0;
-
-       /* Write the location of the TFDList to the IPG. */
-       IPG_DDEBUG_MSG("Starting TFDListPtr = %08x\n",
-                      (u32) sp->txd_map);
-       ipg_w32((u32) sp->txd_map, TFD_LIST_PTR_0);
-       ipg_w32(0x00000000, TFD_LIST_PTR_1);
-
-       sp->reset_current_tfd = 1;
-}
-
-/*
- * Free all transmit buffers which have already been transferred
- * via DMA to the IPG.
- */
-static void ipg_nic_txfree(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       unsigned int released, pending, dirty;
-
-       IPG_DEBUG_MSG("_nic_txfree\n");
-
-       pending = sp->tx_current - sp->tx_dirty;
-       dirty = sp->tx_dirty % IPG_TFDLIST_LENGTH;
-
-       for (released = 0; released < pending; released++) {
-               struct sk_buff *skb = sp->tx_buff[dirty];
-               struct ipg_tx *txfd = sp->txd + dirty;
-
-               IPG_DEBUG_MSG("TFC = %016lx\n", (unsigned long) txfd->tfc);
-
-               /* Look at each TFD's TFC field beginning
-                * at the last freed TFD up to the current TFD.
-                * If the TFDDone bit is set, free the associated
-                * buffer.
-                */
-               if (!(txfd->tfc & cpu_to_le64(IPG_TFC_TFDDONE)))
-                        break;
-
-               /* Free the transmit buffer. */
-               if (skb) {
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN,
-                               skb->len, PCI_DMA_TODEVICE);
-
-                       dev_kfree_skb_irq(skb);
-
-                       sp->tx_buff[dirty] = NULL;
-               }
-               dirty = (dirty + 1) % IPG_TFDLIST_LENGTH;
-       }
-
-       sp->tx_dirty += released;
-
-       if (netif_queue_stopped(dev) &&
-           (sp->tx_current != (sp->tx_dirty + IPG_TFDLIST_LENGTH))) {
-               netif_wake_queue(dev);
-       }
-}
-
-static void ipg_tx_timeout(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-
-       ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA | IPG_AC_NETWORK |
-                 IPG_AC_FIFO);
-
-       spin_lock_irq(&sp->lock);
-
-       /* Re-configure after DMA reset. */
-       if (ipg_io_config(dev) < 0)
-               netdev_info(dev, "Error during re-configuration\n");
-
-       init_tfdlist(dev);
-
-       spin_unlock_irq(&sp->lock);
-
-       ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & IPG_MC_RSVD_MASK,
-               MAC_CTRL);
-}
-
-/*
- * For TxComplete interrupts, free all transmit
- * buffers which have already been transferred via DMA
- * to the IPG.
- */
-static void ipg_nic_txcleanup(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-
-       IPG_DEBUG_MSG("_nic_txcleanup\n");
-
-       for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
-               /* Reading the TXSTATUS register clears the
-                * TX_COMPLETE interrupt.
-                */
-               u32 txstatusdword = ipg_r32(TX_STATUS);
-
-               IPG_DEBUG_MSG("TxStatus = %08x\n", txstatusdword);
-
-               /* Check for Transmit errors. Error bits only valid if
-                * TX_COMPLETE bit in the TXSTATUS register is a 1.
-                */
-               if (!(txstatusdword & IPG_TS_TX_COMPLETE))
-                       break;
-
-               /* If in 10Mbps mode, indicate transmit is ready. */
-               if (sp->tenmbpsmode) {
-                       netif_wake_queue(dev);
-               }
-
-               /* Transmit error, increment stat counters. */
-               if (txstatusdword & IPG_TS_TX_ERROR) {
-                       IPG_DEBUG_MSG("Transmit error\n");
-                       sp->stats.tx_errors++;
-               }
-
-               /* Late collision, re-enable transmitter. */
-               if (txstatusdword & IPG_TS_LATE_COLLISION) {
-                       IPG_DEBUG_MSG("Late collision on transmit\n");
-                       ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
-                               IPG_MC_RSVD_MASK, MAC_CTRL);
-               }
-
-               /* Maximum collisions, re-enable transmitter. */
-               if (txstatusdword & IPG_TS_TX_MAX_COLL) {
-                       IPG_DEBUG_MSG("Maximum collisions on transmit\n");
-                       ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
-                               IPG_MC_RSVD_MASK, MAC_CTRL);
-               }
-
-               /* Transmit underrun, reset and re-enable
-                * transmitter.
-                */
-               if (txstatusdword & IPG_TS_TX_UNDERRUN) {
-                       IPG_DEBUG_MSG("Transmitter underrun\n");
-                       sp->stats.tx_fifo_errors++;
-                       ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA |
-                                 IPG_AC_NETWORK | IPG_AC_FIFO);
-
-                       /* Re-configure after DMA reset. */
-                       if (ipg_io_config(dev) < 0) {
-                               netdev_info(dev, "Error during re-configuration\n");
-                       }
-                       init_tfdlist(dev);
-
-                       ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) &
-                               IPG_MC_RSVD_MASK, MAC_CTRL);
-               }
-       }
-
-       ipg_nic_txfree(dev);
-}
-
-/* Provides statistical information about the IPG NIC. */
-static struct net_device_stats *ipg_nic_get_stats(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       u16 temp1;
-       u16 temp2;
-
-       IPG_DEBUG_MSG("_nic_get_stats\n");
-
-       /* Check to see if the NIC has been initialized via nic_open,
-        * before trying to read statistic registers.
-        */
-       if (!netif_running(dev))
-               return &sp->stats;
-
-       sp->stats.rx_packets += ipg_r32(IPG_FRAMESRCVDOK);
-       sp->stats.tx_packets += ipg_r32(IPG_FRAMESXMTDOK);
-       sp->stats.rx_bytes += ipg_r32(IPG_OCTETRCVOK);
-       sp->stats.tx_bytes += ipg_r32(IPG_OCTETXMTOK);
-       temp1 = ipg_r16(IPG_FRAMESLOSTRXERRORS);
-       sp->stats.rx_errors += temp1;
-       sp->stats.rx_missed_errors += temp1;
-       temp1 = ipg_r32(IPG_SINGLECOLFRAMES) + ipg_r32(IPG_MULTICOLFRAMES) +
-               ipg_r32(IPG_LATECOLLISIONS);
-       temp2 = ipg_r16(IPG_CARRIERSENSEERRORS);
-       sp->stats.collisions += temp1;
-       sp->stats.tx_dropped += ipg_r16(IPG_FRAMESABORTXSCOLLS);
-       sp->stats.tx_errors += ipg_r16(IPG_FRAMESWEXDEFERRAL) +
-               ipg_r32(IPG_FRAMESWDEFERREDXMT) + temp1 + temp2;
-       sp->stats.multicast += ipg_r32(IPG_MCSTOCTETRCVDOK);
-
-       /* detailed tx_errors */
-       sp->stats.tx_carrier_errors += temp2;
-
-       /* detailed rx_errors */
-       sp->stats.rx_length_errors += ipg_r16(IPG_INRANGELENGTHERRORS) +
-               ipg_r16(IPG_FRAMETOOLONGERRORS);
-       sp->stats.rx_crc_errors += ipg_r16(IPG_FRAMECHECKSEQERRORS);
-
-       /* Unutilized IPG statistic registers. */
-       ipg_r32(IPG_MCSTFRAMESRCVDOK);
-
-       return &sp->stats;
-}
-
-/* Restore used receive buffers. */
-static int ipg_nic_rxrestore(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       const unsigned int curr = sp->rx_current;
-       unsigned int dirty = sp->rx_dirty;
-
-       IPG_DEBUG_MSG("_nic_rxrestore\n");
-
-       for (dirty = sp->rx_dirty; curr - dirty > 0; dirty++) {
-               unsigned int entry = dirty % IPG_RFDLIST_LENGTH;
-
-               /* rx_copybreak may poke hole here and there. */
-               if (sp->rx_buff[entry])
-                       continue;
-
-               /* Generate a new receive buffer to replace the
-                * current buffer (which will be released by the
-                * Linux system).
-                */
-               if (ipg_get_rxbuff(dev, entry) < 0) {
-                       IPG_DEBUG_MSG("Cannot allocate new Rx buffer\n");
-
-                       break;
-               }
-
-               /* Reset the RFS field. */
-               sp->rxd[entry].rfs = 0x0000000000000000;
-       }
-       sp->rx_dirty = dirty;
-
-       return 0;
-}
-
-/* use jumboindex and jumbosize to control jumbo frame status
- * initial status is jumboindex=-1 and jumbosize=0
- * 1. jumboindex = -1 and jumbosize=0 : previous jumbo frame has been done.
- * 2. jumboindex != -1 and jumbosize != 0 : jumbo frame is not over size and receiving
- * 3. jumboindex = -1 and jumbosize != 0 : jumbo frame is over size, already dump
- *               previous receiving and need to continue dumping the current one
- */
-enum {
-       NORMAL_PACKET,
-       ERROR_PACKET
-};
-
-enum {
-       FRAME_NO_START_NO_END   = 0,
-       FRAME_WITH_START                = 1,
-       FRAME_WITH_END          = 10,
-       FRAME_WITH_START_WITH_END = 11
-};
-
-static void ipg_nic_rx_free_skb(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH;
-
-       if (sp->rx_buff[entry]) {
-               struct ipg_rx *rxfd = sp->rxd + entry;
-
-               pci_unmap_single(sp->pdev,
-                       le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                       sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-               dev_kfree_skb_irq(sp->rx_buff[entry]);
-               sp->rx_buff[entry] = NULL;
-       }
-}
-
-static int ipg_nic_rx_check_frame_type(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       struct ipg_rx *rxfd = sp->rxd + (sp->rx_current % IPG_RFDLIST_LENGTH);
-       int type = FRAME_NO_START_NO_END;
-
-       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART)
-               type += FRAME_WITH_START;
-       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND)
-               type += FRAME_WITH_END;
-       return type;
-}
-
-static int ipg_nic_rx_check_error(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH;
-       struct ipg_rx *rxfd = sp->rxd + entry;
-
-       if (IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) &
-            (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
-             IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
-             IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) {
-               IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
-                             (unsigned long) rxfd->rfs);
-
-               /* Increment general receive error statistic. */
-               sp->stats.rx_errors++;
-
-               /* Increment detailed receive error statistics. */
-               if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-                       IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
-
-                       sp->stats.rx_fifo_errors++;
-               }
-
-               if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-                       IPG_DEBUG_MSG("RX runt occurred\n");
-                       sp->stats.rx_length_errors++;
-               }
-
-               /* Do nothing for IPG_RFS_RXOVERSIZEDFRAME,
-                * error count handled by a IPG statistic register.
-                */
-
-               if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-                       IPG_DEBUG_MSG("RX alignment error occurred\n");
-                       sp->stats.rx_frame_errors++;
-               }
-
-               /* Do nothing for IPG_RFS_RXFCSERROR, error count
-                * handled by a IPG statistic register.
-                */
-
-               /* Free the memory associated with the RX
-                * buffer since it is erroneous and we will
-                * not pass it to higher layer processes.
-                */
-               if (sp->rx_buff[entry]) {
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                               sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
-                       dev_kfree_skb_irq(sp->rx_buff[entry]);
-                       sp->rx_buff[entry] = NULL;
-               }
-               return ERROR_PACKET;
-       }
-       return NORMAL_PACKET;
-}
-
-static void ipg_nic_rx_with_start_and_end(struct net_device *dev,
-                                         struct ipg_nic_private *sp,
-                                         struct ipg_rx *rxfd, unsigned entry)
-{
-       struct ipg_jumbo *jumbo = &sp->jumbo;
-       struct sk_buff *skb;
-       int framelen;
-
-       if (jumbo->found_start) {
-               dev_kfree_skb_irq(jumbo->skb);
-               jumbo->found_start = 0;
-               jumbo->current_size = 0;
-               jumbo->skb = NULL;
-       }
-
-       /* 1: found error, 0 no error */
-       if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET)
-               return;
-
-       skb = sp->rx_buff[entry];
-       if (!skb)
-               return;
-
-       /* accept this frame and send to upper layer */
-       framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
-       if (framelen > sp->rxfrag_size)
-               framelen = sp->rxfrag_size;
-
-       skb_put(skb, framelen);
-       skb->protocol = eth_type_trans(skb, dev);
-       skb_checksum_none_assert(skb);
-       netif_rx(skb);
-       sp->rx_buff[entry] = NULL;
-}
-
-static void ipg_nic_rx_with_start(struct net_device *dev,
-                                 struct ipg_nic_private *sp,
-                                 struct ipg_rx *rxfd, unsigned entry)
-{
-       struct ipg_jumbo *jumbo = &sp->jumbo;
-       struct pci_dev *pdev = sp->pdev;
-       struct sk_buff *skb;
-
-       /* 1: found error, 0 no error */
-       if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET)
-               return;
-
-       /* accept this frame and send to upper layer */
-       skb = sp->rx_buff[entry];
-       if (!skb)
-               return;
-
-       if (jumbo->found_start)
-               dev_kfree_skb_irq(jumbo->skb);
-
-       pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                        sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
-       skb_put(skb, sp->rxfrag_size);
-
-       jumbo->found_start = 1;
-       jumbo->current_size = sp->rxfrag_size;
-       jumbo->skb = skb;
-
-       sp->rx_buff[entry] = NULL;
-}
-
-static void ipg_nic_rx_with_end(struct net_device *dev,
-                               struct ipg_nic_private *sp,
-                               struct ipg_rx *rxfd, unsigned entry)
-{
-       struct ipg_jumbo *jumbo = &sp->jumbo;
-
-       /* 1: found error, 0 no error */
-       if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) {
-               struct sk_buff *skb = sp->rx_buff[entry];
-
-               if (!skb)
-                       return;
-
-               if (jumbo->found_start) {
-                       int framelen, endframelen;
-
-                       framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
-
-                       endframelen = framelen - jumbo->current_size;
-                       if (framelen > sp->rxsupport_size)
-                               dev_kfree_skb_irq(jumbo->skb);
-                       else {
-                               memcpy(skb_put(jumbo->skb, endframelen),
-                                      skb->data, endframelen);
-
-                               jumbo->skb->protocol =
-                                   eth_type_trans(jumbo->skb, dev);
-
-                               skb_checksum_none_assert(jumbo->skb);
-                               netif_rx(jumbo->skb);
-                       }
-               }
-
-               jumbo->found_start = 0;
-               jumbo->current_size = 0;
-               jumbo->skb = NULL;
-
-               ipg_nic_rx_free_skb(dev);
-       } else {
-               dev_kfree_skb_irq(jumbo->skb);
-               jumbo->found_start = 0;
-               jumbo->current_size = 0;
-               jumbo->skb = NULL;
-       }
-}
-
-static void ipg_nic_rx_no_start_no_end(struct net_device *dev,
-                                      struct ipg_nic_private *sp,
-                                      struct ipg_rx *rxfd, unsigned entry)
-{
-       struct ipg_jumbo *jumbo = &sp->jumbo;
-
-       /* 1: found error, 0 no error */
-       if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) {
-               struct sk_buff *skb = sp->rx_buff[entry];
-
-               if (skb) {
-                       if (jumbo->found_start) {
-                               jumbo->current_size += sp->rxfrag_size;
-                               if (jumbo->current_size <= sp->rxsupport_size) {
-                                       memcpy(skb_put(jumbo->skb,
-                                                      sp->rxfrag_size),
-                                              skb->data, sp->rxfrag_size);
-                               }
-                       }
-                       ipg_nic_rx_free_skb(dev);
-               }
-       } else {
-               dev_kfree_skb_irq(jumbo->skb);
-               jumbo->found_start = 0;
-               jumbo->current_size = 0;
-               jumbo->skb = NULL;
-       }
-}
-
-static int ipg_nic_rx_jumbo(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       unsigned int curr = sp->rx_current;
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-
-       IPG_DEBUG_MSG("_nic_rx\n");
-
-       for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) {
-               unsigned int entry = curr % IPG_RFDLIST_LENGTH;
-               struct ipg_rx *rxfd = sp->rxd + entry;
-
-               if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE)))
-                       break;
-
-               switch (ipg_nic_rx_check_frame_type(dev)) {
-               case FRAME_WITH_START_WITH_END:
-                       ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry);
-                       break;
-               case FRAME_WITH_START:
-                       ipg_nic_rx_with_start(dev, sp, rxfd, entry);
-                       break;
-               case FRAME_WITH_END:
-                       ipg_nic_rx_with_end(dev, sp, rxfd, entry);
-                       break;
-               case FRAME_NO_START_NO_END:
-                       ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry);
-                       break;
-               }
-       }
-
-       sp->rx_current = curr;
-
-       if (i == IPG_MAXRFDPROCESS_COUNT) {
-               /* There are more RFDs to process, however the
-                * allocated amount of RFD processing time has
-                * expired. Assert Interrupt Requested to make
-                * sure we come back to process the remaining RFDs.
-                */
-               ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL);
-       }
-
-       ipg_nic_rxrestore(dev);
-
-       return 0;
-}
-
-static int ipg_nic_rx(struct net_device *dev)
-{
-       /* Transfer received Ethernet frames to higher network layers. */
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       unsigned int curr = sp->rx_current;
-       void __iomem *ioaddr = sp->ioaddr;
-       struct ipg_rx *rxfd;
-       unsigned int i;
-
-       IPG_DEBUG_MSG("_nic_rx\n");
-
-#define __RFS_MASK \
-       cpu_to_le64(IPG_RFS_RFDDONE | IPG_RFS_FRAMESTART | IPG_RFS_FRAMEEND)
-
-       for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) {
-               unsigned int entry = curr % IPG_RFDLIST_LENGTH;
-               struct sk_buff *skb = sp->rx_buff[entry];
-               unsigned int framelen;
-
-               rxfd = sp->rxd + entry;
-
-               if (((rxfd->rfs & __RFS_MASK) != __RFS_MASK) || !skb)
-                       break;
-
-               /* Get received frame length. */
-               framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
-
-               /* Check for jumbo frame arrival with too small
-                * RXFRAG_SIZE.
-                */
-               if (framelen > sp->rxfrag_size) {
-                       IPG_DEBUG_MSG
-                           ("RFS FrameLen > allocated fragment size\n");
-
-                       framelen = sp->rxfrag_size;
-               }
-
-               if ((IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) &
-                      (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME |
-                       IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR |
-                       IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR)))) {
-
-                       IPG_DEBUG_MSG("Rx error, RFS = %016lx\n",
-                                     (unsigned long int) rxfd->rfs);
-
-                       /* Increment general receive error statistic. */
-                       sp->stats.rx_errors++;
-
-                       /* Increment detailed receive error statistics. */
-                       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-                               IPG_DEBUG_MSG("RX FIFO overrun occurred\n");
-                               sp->stats.rx_fifo_errors++;
-                       }
-
-                       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-                               IPG_DEBUG_MSG("RX runt occurred\n");
-                               sp->stats.rx_length_errors++;
-                       }
-
-                       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXOVERSIZEDFRAME) ;
-                       /* Do nothing, error count handled by a IPG
-                        * statistic register.
-                        */
-
-                       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-                               IPG_DEBUG_MSG("RX alignment error occurred\n");
-                               sp->stats.rx_frame_errors++;
-                       }
-
-                       if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFCSERROR) ;
-                       /* Do nothing, error count handled by a IPG
-                        * statistic register.
-                        */
-
-                       /* Free the memory associated with the RX
-                        * buffer since it is erroneous and we will
-                        * not pass it to higher layer processes.
-                        */
-                       if (skb) {
-                               __le64 info = rxfd->frag_info;
-
-                               pci_unmap_single(sp->pdev,
-                                       le64_to_cpu(info) & ~IPG_RFI_FRAGLEN,
-                                       sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
-                               dev_kfree_skb_irq(skb);
-                       }
-               } else {
-
-                       /* Adjust the new buffer length to accommodate the size
-                        * of the received frame.
-                        */
-                       skb_put(skb, framelen);
-
-                       /* Set the buffer's protocol field to Ethernet. */
-                       skb->protocol = eth_type_trans(skb, dev);
-
-                       /* The IPG encountered an error with (or
-                        * there were no) IP/TCP/UDP checksums.
-                        * This may or may not indicate an invalid
-                        * IP/TCP/UDP frame was received. Let the
-                        * upper layer decide.
-                        */
-                       skb_checksum_none_assert(skb);
-
-                       /* Hand off frame for higher layer processing.
-                        * The function netif_rx() releases the sk_buff
-                        * when processing completes.
-                        */
-                       netif_rx(skb);
-               }
-
-               /* Assure RX buffer is not reused by IPG. */
-               sp->rx_buff[entry] = NULL;
-       }
-
-       /*
-        * If there are more RFDs to process and the allocated amount of RFD
-        * processing time has expired, assert Interrupt Requested to make
-        * sure we come back to process the remaining RFDs.
-        */
-       if (i == IPG_MAXRFDPROCESS_COUNT)
-               ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL);
-
-#ifdef IPG_DEBUG
-       /* Check if the RFD list contained no receive frame data. */
-       if (!i)
-               sp->EmptyRFDListCount++;
-#endif
-       while ((le64_to_cpu(rxfd->rfs) & IPG_RFS_RFDDONE) &&
-              !((le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART) &&
-                (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND))) {
-               unsigned int entry = curr++ % IPG_RFDLIST_LENGTH;
-
-               rxfd = sp->rxd + entry;
-
-               IPG_DEBUG_MSG("Frame requires multiple RFDs\n");
-
-               /* An unexpected event, additional code needed to handle
-                * properly. So for the time being, just disregard the
-                * frame.
-                */
-
-               /* Free the memory associated with the RX
-                * buffer since it is erroneous and we will
-                * not pass it to higher layer processes.
-                */
-               if (sp->rx_buff[entry]) {
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                               sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb_irq(sp->rx_buff[entry]);
-               }
-
-               /* Assure RX buffer is not reused by IPG. */
-               sp->rx_buff[entry] = NULL;
-       }
-
-       sp->rx_current = curr;
-
-       /* Check to see if there are a minimum number of used
-        * RFDs before restoring any (should improve performance.)
-        */
-       if ((curr - sp->rx_dirty) >= IPG_MINUSEDRFDSTOFREE)
-               ipg_nic_rxrestore(dev);
-
-       return 0;
-}
-
-static void ipg_reset_after_host_error(struct work_struct *work)
-{
-       struct ipg_nic_private *sp =
-               container_of(work, struct ipg_nic_private, task.work);
-       struct net_device *dev = sp->dev;
-
-       /*
-        * Acknowledge HostError interrupt by resetting
-        * IPG DMA and HOST.
-        */
-       ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA);
-
-       init_rfdlist(dev);
-       init_tfdlist(dev);
-
-       if (ipg_io_config(dev) < 0) {
-               netdev_info(dev, "Cannot recover from PCI error\n");
-               schedule_delayed_work(&sp->task, HZ);
-       }
-}
-
-static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst)
-{
-       struct net_device *dev = dev_inst;
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int handled = 0;
-       u16 status;
-
-       IPG_DEBUG_MSG("_interrupt_handler\n");
-
-       if (sp->is_jumbo)
-               ipg_nic_rxrestore(dev);
-
-       spin_lock(&sp->lock);
-
-       /* Get interrupt source information, and acknowledge
-        * some (i.e. TxDMAComplete, RxDMAComplete, RxEarly,
-        * IntRequested, MacControlFrame, LinkEvent) interrupts
-        * if issued. Also, all IPG interrupts are disabled by
-        * reading IntStatusAck.
-        */
-       status = ipg_r16(INT_STATUS_ACK);
-
-       IPG_DEBUG_MSG("IntStatusAck = %04x\n", status);
-
-       /* Shared IRQ of remove event. */
-       if (!(status & IPG_IS_RSVD_MASK))
-               goto out_enable;
-
-       handled = 1;
-
-       if (unlikely(!netif_running(dev)))
-               goto out_unlock;
-
-       /* If RFDListEnd interrupt, restore all used RFDs. */
-       if (status & IPG_IS_RFD_LIST_END) {
-               IPG_DEBUG_MSG("RFDListEnd Interrupt\n");
-
-               /* The RFD list end indicates an RFD was encountered
-                * with a 0 NextPtr, or with an RFDDone bit set to 1
-                * (indicating the RFD is not read for use by the
-                * IPG.) Try to restore all RFDs.
-                */
-               ipg_nic_rxrestore(dev);
-
-#ifdef IPG_DEBUG
-               /* Increment the RFDlistendCount counter. */
-               sp->RFDlistendCount++;
-#endif
-       }
-
-       /* If RFDListEnd, RxDMAPriority, RxDMAComplete, or
-        * IntRequested interrupt, process received frames. */
-       if ((status & IPG_IS_RX_DMA_PRIORITY) ||
-           (status & IPG_IS_RFD_LIST_END) ||
-           (status & IPG_IS_RX_DMA_COMPLETE) ||
-           (status & IPG_IS_INT_REQUESTED)) {
-#ifdef IPG_DEBUG
-               /* Increment the RFD list checked counter if interrupted
-                * only to check the RFD list. */
-               if (status & (~(IPG_IS_RX_DMA_PRIORITY | IPG_IS_RFD_LIST_END |
-                               IPG_IS_RX_DMA_COMPLETE | IPG_IS_INT_REQUESTED) &
-                              (IPG_IS_HOST_ERROR | IPG_IS_TX_DMA_COMPLETE |
-                               IPG_IS_LINK_EVENT | IPG_IS_TX_COMPLETE |
-                               IPG_IS_UPDATE_STATS)))
-                       sp->RFDListCheckedCount++;
-#endif
-
-               if (sp->is_jumbo)
-                       ipg_nic_rx_jumbo(dev);
-               else
-                       ipg_nic_rx(dev);
-       }
-
-       /* If TxDMAComplete interrupt, free used TFDs. */
-       if (status & IPG_IS_TX_DMA_COMPLETE)
-               ipg_nic_txfree(dev);
-
-       /* TxComplete interrupts indicate one of numerous actions.
-        * Determine what action to take based on TXSTATUS register.
-        */
-       if (status & IPG_IS_TX_COMPLETE)
-               ipg_nic_txcleanup(dev);
-
-       /* If UpdateStats interrupt, update Linux Ethernet statistics */
-       if (status & IPG_IS_UPDATE_STATS)
-               ipg_nic_get_stats(dev);
-
-       /* If HostError interrupt, reset IPG. */
-       if (status & IPG_IS_HOST_ERROR) {
-               IPG_DDEBUG_MSG("HostError Interrupt\n");
-
-               schedule_delayed_work(&sp->task, 0);
-       }
-
-       /* If LinkEvent interrupt, resolve autonegotiation. */
-       if (status & IPG_IS_LINK_EVENT) {
-               if (ipg_config_autoneg(dev) < 0)
-                       netdev_info(dev, "Auto-negotiation error\n");
-       }
-
-       /* If MACCtrlFrame interrupt, do nothing. */
-       if (status & IPG_IS_MAC_CTRL_FRAME)
-               IPG_DEBUG_MSG("MACCtrlFrame interrupt\n");
-
-       /* If RxComplete interrupt, do nothing. */
-       if (status & IPG_IS_RX_COMPLETE)
-               IPG_DEBUG_MSG("RxComplete interrupt\n");
-
-       /* If RxEarly interrupt, do nothing. */
-       if (status & IPG_IS_RX_EARLY)
-               IPG_DEBUG_MSG("RxEarly interrupt\n");
-
-out_enable:
-       /* Re-enable IPG interrupts. */
-       ipg_w16(IPG_IE_TX_DMA_COMPLETE | IPG_IE_RX_DMA_COMPLETE |
-               IPG_IE_HOST_ERROR | IPG_IE_INT_REQUESTED | IPG_IE_TX_COMPLETE |
-               IPG_IE_LINK_EVENT | IPG_IE_UPDATE_STATS, INT_ENABLE);
-out_unlock:
-       spin_unlock(&sp->lock);
-
-       return IRQ_RETVAL(handled);
-}
-
-static void ipg_rx_clear(struct ipg_nic_private *sp)
-{
-       unsigned int i;
-
-       for (i = 0; i < IPG_RFDLIST_LENGTH; i++) {
-               if (sp->rx_buff[i]) {
-                       struct ipg_rx *rxfd = sp->rxd + i;
-
-                       dev_kfree_skb_irq(sp->rx_buff[i]);
-                       sp->rx_buff[i] = NULL;
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN,
-                               sp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-               }
-       }
-}
-
-static void ipg_tx_clear(struct ipg_nic_private *sp)
-{
-       unsigned int i;
-
-       for (i = 0; i < IPG_TFDLIST_LENGTH; i++) {
-               if (sp->tx_buff[i]) {
-                       struct ipg_tx *txfd = sp->txd + i;
-
-                       pci_unmap_single(sp->pdev,
-                               le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN,
-                               sp->tx_buff[i]->len, PCI_DMA_TODEVICE);
-
-                       dev_kfree_skb_irq(sp->tx_buff[i]);
-
-                       sp->tx_buff[i] = NULL;
-               }
-       }
-}
-
-static int ipg_nic_open(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       struct pci_dev *pdev = sp->pdev;
-       int rc;
-
-       IPG_DEBUG_MSG("_nic_open\n");
-
-       sp->rx_buf_sz = sp->rxsupport_size;
-
-       /* Check for interrupt line conflicts, and request interrupt
-        * line for IPG.
-        *
-        * IMPORTANT: Disable IPG interrupts prior to registering
-        *            IRQ.
-        */
-       ipg_w16(0x0000, INT_ENABLE);
-
-       /* Register the interrupt line to be used by the IPG within
-        * the Linux system.
-        */
-       rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED,
-                        dev->name, dev);
-       if (rc < 0) {
-               netdev_info(dev, "Error when requesting interrupt\n");
-               goto out;
-       }
-
-       dev->irq = pdev->irq;
-
-       rc = -ENOMEM;
-
-       sp->rxd = dma_alloc_coherent(&pdev->dev, IPG_RX_RING_BYTES,
-                                    &sp->rxd_map, GFP_KERNEL);
-       if (!sp->rxd)
-               goto err_free_irq_0;
-
-       sp->txd = dma_alloc_coherent(&pdev->dev, IPG_TX_RING_BYTES,
-                                    &sp->txd_map, GFP_KERNEL);
-       if (!sp->txd)
-               goto err_free_rx_1;
-
-       rc = init_rfdlist(dev);
-       if (rc < 0) {
-               netdev_info(dev, "Error during configuration\n");
-               goto err_free_tx_2;
-       }
-
-       init_tfdlist(dev);
-
-       rc = ipg_io_config(dev);
-       if (rc < 0) {
-               netdev_info(dev, "Error during configuration\n");
-               goto err_release_tfdlist_3;
-       }
-
-       /* Resolve autonegotiation. */
-       if (ipg_config_autoneg(dev) < 0)
-               netdev_info(dev, "Auto-negotiation error\n");
-
-       /* initialize JUMBO Frame control variable */
-       sp->jumbo.found_start = 0;
-       sp->jumbo.current_size = 0;
-       sp->jumbo.skb = NULL;
-
-       /* Enable transmit and receive operation of the IPG. */
-       ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_RX_ENABLE | IPG_MC_TX_ENABLE) &
-                IPG_MC_RSVD_MASK, MAC_CTRL);
-
-       netif_start_queue(dev);
-out:
-       return rc;
-
-err_release_tfdlist_3:
-       ipg_tx_clear(sp);
-       ipg_rx_clear(sp);
-err_free_tx_2:
-       dma_free_coherent(&pdev->dev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map);
-err_free_rx_1:
-       dma_free_coherent(&pdev->dev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map);
-err_free_irq_0:
-       free_irq(pdev->irq, dev);
-       goto out;
-}
-
-static int ipg_nic_stop(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       struct pci_dev *pdev = sp->pdev;
-
-       IPG_DEBUG_MSG("_nic_stop\n");
-
-       netif_stop_queue(dev);
-
-       IPG_DUMPTFDLIST(dev);
-
-       do {
-               (void) ipg_r16(INT_STATUS_ACK);
-
-               ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA);
-
-               synchronize_irq(pdev->irq);
-       } while (ipg_r16(INT_ENABLE) & IPG_IE_RSVD_MASK);
-
-       ipg_rx_clear(sp);
-
-       ipg_tx_clear(sp);
-
-       pci_free_consistent(pdev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map);
-       pci_free_consistent(pdev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map);
-
-       free_irq(pdev->irq, dev);
-
-       return 0;
-}
-
-static netdev_tx_t ipg_nic_hard_start_xmit(struct sk_buff *skb,
-                                          struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int entry = sp->tx_current % IPG_TFDLIST_LENGTH;
-       unsigned long flags;
-       struct ipg_tx *txfd;
-
-       IPG_DDEBUG_MSG("_nic_hard_start_xmit\n");
-
-       /* If in 10Mbps mode, stop the transmit queue so
-        * no more transmit frames are accepted.
-        */
-       if (sp->tenmbpsmode)
-               netif_stop_queue(dev);
-
-       if (sp->reset_current_tfd) {
-               sp->reset_current_tfd = 0;
-               entry = 0;
-       }
-
-       txfd = sp->txd + entry;
-
-       sp->tx_buff[entry] = skb;
-
-       /* Clear all TFC fields, except TFDDONE. */
-       txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE);
-
-       /* Specify the TFC field within the TFD. */
-       txfd->tfc |= cpu_to_le64(IPG_TFC_WORDALIGNDISABLED |
-               (IPG_TFC_FRAMEID & sp->tx_current) |
-               (IPG_TFC_FRAGCOUNT & (1 << 24)));
-       /*
-        * 16--17 (WordAlign) <- 3 (disable),
-        * 0--15 (FrameId) <- sp->tx_current,
-        * 24--27 (FragCount) <- 1
-        */
-
-       /* Request TxComplete interrupts at an interval defined
-        * by the constant IPG_FRAMESBETWEENTXCOMPLETES.
-        * Request TxComplete interrupt for every frame
-        * if in 10Mbps mode to accommodate problem with 10Mbps
-        * processing.
-        */
-       if (sp->tenmbpsmode)
-               txfd->tfc |= cpu_to_le64(IPG_TFC_TXINDICATE);
-       txfd->tfc |= cpu_to_le64(IPG_TFC_TXDMAINDICATE);
-       /* Based on compilation option, determine if FCS is to be
-        * appended to transmit frame by IPG.
-        */
-       if (!(IPG_APPEND_FCS_ON_TX))
-               txfd->tfc |= cpu_to_le64(IPG_TFC_FCSAPPENDDISABLE);
-
-       /* Based on compilation option, determine if IP, TCP and/or
-        * UDP checksums are to be added to transmit frame by IPG.
-        */
-       if (IPG_ADD_IPCHECKSUM_ON_TX)
-               txfd->tfc |= cpu_to_le64(IPG_TFC_IPCHECKSUMENABLE);
-
-       if (IPG_ADD_TCPCHECKSUM_ON_TX)
-               txfd->tfc |= cpu_to_le64(IPG_TFC_TCPCHECKSUMENABLE);
-
-       if (IPG_ADD_UDPCHECKSUM_ON_TX)
-               txfd->tfc |= cpu_to_le64(IPG_TFC_UDPCHECKSUMENABLE);
-
-       /* Based on compilation option, determine if VLAN tag info is to be
-        * inserted into transmit frame by IPG.
-        */
-       if (IPG_INSERT_MANUAL_VLAN_TAG) {
-               txfd->tfc |= cpu_to_le64(IPG_TFC_VLANTAGINSERT |
-                       ((u64) IPG_MANUAL_VLAN_VID << 32) |
-                       ((u64) IPG_MANUAL_VLAN_CFI << 44) |
-                       ((u64) IPG_MANUAL_VLAN_USERPRIORITY << 45));
-       }
-
-       /* The fragment start location within system memory is defined
-        * by the sk_buff structure's data field. The physical address
-        * of this location within the system's virtual memory space
-        * is determined using the IPG_HOST2BUS_MAP function.
-        */
-       txfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data,
-               skb->len, PCI_DMA_TODEVICE));
-
-       /* The length of the fragment within system memory is defined by
-        * the sk_buff structure's len field.
-        */
-       txfd->frag_info |= cpu_to_le64(IPG_TFI_FRAGLEN &
-               ((u64) (skb->len & 0xffff) << 48));
-
-       /* Clear the TFDDone bit last to indicate the TFD is ready
-        * for transfer to the IPG.
-        */
-       txfd->tfc &= cpu_to_le64(~IPG_TFC_TFDDONE);
-
-       spin_lock_irqsave(&sp->lock, flags);
-
-       sp->tx_current++;
-
-       mmiowb();
-
-       ipg_w32(IPG_DC_TX_DMA_POLL_NOW, DMA_CTRL);
-
-       if (sp->tx_current == (sp->tx_dirty + IPG_TFDLIST_LENGTH))
-               netif_stop_queue(dev);
-
-       spin_unlock_irqrestore(&sp->lock, flags);
-
-       return NETDEV_TX_OK;
-}
-
-static void ipg_set_phy_default_param(unsigned char rev,
-                                     struct net_device *dev, int phy_address)
-{
-       unsigned short length;
-       unsigned char revision;
-       const unsigned short *phy_param;
-       unsigned short address, value;
-
-       phy_param = &DefaultPhyParam[0];
-       length = *phy_param & 0x00FF;
-       revision = (unsigned char)((*phy_param) >> 8);
-       phy_param++;
-       while (length != 0) {
-               if (rev == revision) {
-                       while (length > 1) {
-                               address = *phy_param;
-                               value = *(phy_param + 1);
-                               phy_param += 2;
-                               mdio_write(dev, phy_address, address, value);
-                               length -= 4;
-                       }
-                       break;
-               } else {
-                       phy_param += length / 2;
-                       length = *phy_param & 0x00FF;
-                       revision = (unsigned char)((*phy_param) >> 8);
-                       phy_param++;
-               }
-       }
-}
-
-static int read_eeprom(struct net_device *dev, int eep_addr)
-{
-       void __iomem *ioaddr = ipg_ioaddr(dev);
-       unsigned int i;
-       int ret = 0;
-       u16 value;
-
-       value = IPG_EC_EEPROM_READOPCODE | (eep_addr & 0xff);
-       ipg_w16(value, EEPROM_CTRL);
-
-       for (i = 0; i < 1000; i++) {
-               u16 data;
-
-               mdelay(10);
-               data = ipg_r16(EEPROM_CTRL);
-               if (!(data & IPG_EC_EEPROM_BUSY)) {
-                       ret = ipg_r16(EEPROM_DATA);
-                       break;
-               }
-       }
-       return ret;
-}
-
-static void ipg_init_mii(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       struct mii_if_info *mii_if = &sp->mii_if;
-       int phyaddr;
-
-       mii_if->dev          = dev;
-       mii_if->mdio_read    = mdio_read;
-       mii_if->mdio_write   = mdio_write;
-       mii_if->phy_id_mask  = 0x1f;
-       mii_if->reg_num_mask = 0x1f;
-
-       mii_if->phy_id = phyaddr = ipg_find_phyaddr(dev);
-
-       if (phyaddr != 0x1f) {
-               u16 mii_phyctrl, mii_1000cr;
-
-               mii_1000cr  = mdio_read(dev, phyaddr, MII_CTRL1000);
-               mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF |
-                       GMII_PHY_1000BASETCONTROL_PreferMaster;
-               mdio_write(dev, phyaddr, MII_CTRL1000, mii_1000cr);
-
-               mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR);
-
-               /* Set default phyparam */
-               ipg_set_phy_default_param(sp->pdev->revision, dev, phyaddr);
-
-               /* Reset PHY */
-               mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART;
-               mdio_write(dev, phyaddr, MII_BMCR, mii_phyctrl);
-
-       }
-}
-
-static int ipg_hw_init(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       void __iomem *ioaddr = sp->ioaddr;
-       unsigned int i;
-       int rc;
-
-       /* Read/Write and Reset EEPROM Value */
-       /* Read LED Mode Configuration from EEPROM */
-       sp->led_mode = read_eeprom(dev, 6);
-
-       /* Reset all functions within the IPG. Do not assert
-        * RST_OUT as not compatible with some PHYs.
-        */
-       rc = ipg_reset(dev, IPG_RESET_MASK);
-       if (rc < 0)
-               goto out;
-
-       ipg_init_mii(dev);
-
-       /* Read MAC Address from EEPROM */
-       for (i = 0; i < 3; i++)
-               sp->station_addr[i] = read_eeprom(dev, 16 + i);
-
-       for (i = 0; i < 3; i++)
-               ipg_w16(sp->station_addr[i], STATION_ADDRESS_0 + 2*i);
-
-       /* Set station address in ethernet_device structure. */
-       dev->dev_addr[0] =  ipg_r16(STATION_ADDRESS_0) & 0x00ff;
-       dev->dev_addr[1] = (ipg_r16(STATION_ADDRESS_0) & 0xff00) >> 8;
-       dev->dev_addr[2] =  ipg_r16(STATION_ADDRESS_1) & 0x00ff;
-       dev->dev_addr[3] = (ipg_r16(STATION_ADDRESS_1) & 0xff00) >> 8;
-       dev->dev_addr[4] =  ipg_r16(STATION_ADDRESS_2) & 0x00ff;
-       dev->dev_addr[5] = (ipg_r16(STATION_ADDRESS_2) & 0xff00) >> 8;
-out:
-       return rc;
-}
-
-static int ipg_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       int rc;
-
-       mutex_lock(&sp->mii_mutex);
-       rc = generic_mii_ioctl(&sp->mii_if, if_mii(ifr), cmd, NULL);
-       mutex_unlock(&sp->mii_mutex);
-
-       return rc;
-}
-
-static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       int err;
-
-       /* Function to accommodate changes to Maximum Transfer Unit
-        * (or MTU) of IPG NIC. Cannot use default function since
-        * the default will not allow for MTU > 1500 bytes.
-        */
-
-       IPG_DEBUG_MSG("_nic_change_mtu\n");
-
-       /*
-        * Check that the new MTU value is between 68 (14 byte header, 46 byte
-        * payload, 4 byte FCS) and 10 KB, which is the largest supported MTU.
-        */
-       if (new_mtu < 68 || new_mtu > 10240)
-               return -EINVAL;
-
-       err = ipg_nic_stop(dev);
-       if (err)
-               return err;
-
-       dev->mtu = new_mtu;
-
-       sp->max_rxframe_size = new_mtu;
-
-       sp->rxfrag_size = new_mtu;
-       if (sp->rxfrag_size > 4088)
-               sp->rxfrag_size = 4088;
-
-       sp->rxsupport_size = sp->max_rxframe_size;
-
-       if (new_mtu > 0x0600)
-               sp->is_jumbo = true;
-       else
-               sp->is_jumbo = false;
-
-       return ipg_nic_open(dev);
-}
-
-static int ipg_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       int rc;
-
-       mutex_lock(&sp->mii_mutex);
-       rc = mii_ethtool_gset(&sp->mii_if, cmd);
-       mutex_unlock(&sp->mii_mutex);
-
-       return rc;
-}
-
-static int ipg_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       int rc;
-
-       mutex_lock(&sp->mii_mutex);
-       rc = mii_ethtool_sset(&sp->mii_if, cmd);
-       mutex_unlock(&sp->mii_mutex);
-
-       return rc;
-}
-
-static int ipg_nway_reset(struct net_device *dev)
-{
-       struct ipg_nic_private *sp = netdev_priv(dev);
-       int rc;
-
-       mutex_lock(&sp->mii_mutex);
-       rc = mii_nway_restart(&sp->mii_if);
-       mutex_unlock(&sp->mii_mutex);
-
-       return rc;
-}
-
-static const struct ethtool_ops ipg_ethtool_ops = {
-       .get_settings = ipg_get_settings,
-       .set_settings = ipg_set_settings,
-       .nway_reset   = ipg_nway_reset,
-};
-
-static void ipg_remove(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct ipg_nic_private *sp = netdev_priv(dev);
-
-       IPG_DEBUG_MSG("_remove\n");
-
-       /* Un-register Ethernet device. */
-       unregister_netdev(dev);
-
-       pci_iounmap(pdev, sp->ioaddr);
-
-       pci_release_regions(pdev);
-
-       free_netdev(dev);
-       pci_disable_device(pdev);
-}
-
-static const struct net_device_ops ipg_netdev_ops = {
-       .ndo_open               = ipg_nic_open,
-       .ndo_stop               = ipg_nic_stop,
-       .ndo_start_xmit         = ipg_nic_hard_start_xmit,
-       .ndo_get_stats          = ipg_nic_get_stats,
-       .ndo_set_rx_mode        = ipg_nic_set_multicast_list,
-       .ndo_do_ioctl           = ipg_ioctl,
-       .ndo_tx_timeout         = ipg_tx_timeout,
-       .ndo_change_mtu         = ipg_nic_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       unsigned int i = id->driver_data;
-       struct ipg_nic_private *sp;
-       struct net_device *dev;
-       void __iomem *ioaddr;
-       int rc;
-
-       rc = pci_enable_device(pdev);
-       if (rc < 0)
-               goto out;
-
-       pr_info("%s: %s\n", pci_name(pdev), ipg_brand_name[i]);
-
-       pci_set_master(pdev);
-
-       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
-       if (rc < 0) {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-               if (rc < 0) {
-                       pr_err("%s: DMA config failed\n", pci_name(pdev));
-                       goto err_disable_0;
-               }
-       }
-
-       /*
-        * Initialize net device.
-        */
-       dev = alloc_etherdev(sizeof(struct ipg_nic_private));
-       if (!dev) {
-               rc = -ENOMEM;
-               goto err_disable_0;
-       }
-
-       sp = netdev_priv(dev);
-       spin_lock_init(&sp->lock);
-       mutex_init(&sp->mii_mutex);
-
-       sp->is_jumbo = IPG_IS_JUMBO;
-       sp->rxfrag_size = IPG_RXFRAG_SIZE;
-       sp->rxsupport_size = IPG_RXSUPPORT_SIZE;
-       sp->max_rxframe_size = IPG_MAX_RXFRAME_SIZE;
-
-       /* Declare IPG NIC functions for Ethernet device methods.
-        */
-       dev->netdev_ops = &ipg_netdev_ops;
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       dev->ethtool_ops = &ipg_ethtool_ops;
-
-       rc = pci_request_regions(pdev, DRV_NAME);
-       if (rc)
-               goto err_free_dev_1;
-
-       ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
-       if (!ioaddr) {
-               pr_err("%s: cannot map MMIO\n", pci_name(pdev));
-               rc = -EIO;
-               goto err_release_regions_2;
-       }
-
-       /* Save the pointer to the PCI device information. */
-       sp->ioaddr = ioaddr;
-       sp->pdev = pdev;
-       sp->dev = dev;
-
-       INIT_DELAYED_WORK(&sp->task, ipg_reset_after_host_error);
-
-       pci_set_drvdata(pdev, dev);
-
-       rc = ipg_hw_init(dev);
-       if (rc < 0)
-               goto err_unmap_3;
-
-       rc = register_netdev(dev);
-       if (rc < 0)
-               goto err_unmap_3;
-
-       netdev_info(dev, "Ethernet device registered\n");
-out:
-       return rc;
-
-err_unmap_3:
-       pci_iounmap(pdev, ioaddr);
-err_release_regions_2:
-       pci_release_regions(pdev);
-err_free_dev_1:
-       free_netdev(dev);
-err_disable_0:
-       pci_disable_device(pdev);
-       goto out;
-}
-
-static struct pci_driver ipg_pci_driver = {
-       .name           = IPG_DRIVER_NAME,
-       .id_table       = ipg_pci_tbl,
-       .probe          = ipg_probe,
-       .remove         = ipg_remove,
-};
-
-module_pci_driver(ipg_pci_driver);
diff --git a/drivers/net/ethernet/icplus/ipg.h b/drivers/net/ethernet/icplus/ipg.h
deleted file mode 100644 (file)
index de60628..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * Include file for Gigabit Ethernet device driver for Network
- * Interface Cards (NICs) utilizing the Tamarack Microelectronics
- * Inc. IPG Gigabit or Triple Speed Ethernet Media Access
- * Controller.
- */
-#ifndef __LINUX_IPG_H
-#define __LINUX_IPG_H
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <asm/bitops.h>
-
-/*
- *     Constants
- */
-
-/* GMII based PHY IDs */
-#define                NS                              0x2000
-#define                MARVELL                         0x0141
-#define                ICPLUS_PHY                      0x243
-
-/* NIC Physical Layer Device MII register fields. */
-#define         MII_PHY_SELECTOR_IEEE8023       0x0001
-#define         MII_PHY_TECHABILITYFIELD        0x1FE0
-
-/* GMII_PHY_1000 need to set to prefer master */
-#define         GMII_PHY_1000BASETCONTROL_PreferMaster 0x0400
-
-/* NIC Physical Layer Device GMII constants. */
-#define         GMII_PREAMBLE                    0xFFFFFFFF
-#define         GMII_ST                          0x1
-#define         GMII_READ                        0x2
-#define         GMII_WRITE                       0x1
-#define         GMII_TA_READ_MASK                0x1
-#define         GMII_TA_WRITE                    0x2
-
-/* I/O register offsets. */
-enum ipg_regs {
-       DMA_CTRL                = 0x00,
-       RX_DMA_STATUS           = 0x08, /* Unused + reserved */
-       TFD_LIST_PTR_0          = 0x10,
-       TFD_LIST_PTR_1          = 0x14,
-       TX_DMA_BURST_THRESH     = 0x18,
-       TX_DMA_URGENT_THRESH    = 0x19,
-       TX_DMA_POLL_PERIOD      = 0x1a,
-       RFD_LIST_PTR_0          = 0x1c,
-       RFD_LIST_PTR_1          = 0x20,
-       RX_DMA_BURST_THRESH     = 0x24,
-       RX_DMA_URGENT_THRESH    = 0x25,
-       RX_DMA_POLL_PERIOD      = 0x26,
-       DEBUG_CTRL              = 0x2c,
-       ASIC_CTRL               = 0x30,
-       FIFO_CTRL               = 0x38, /* Unused */
-       FLOW_OFF_THRESH         = 0x3c,
-       FLOW_ON_THRESH          = 0x3e,
-       EEPROM_DATA             = 0x48,
-       EEPROM_CTRL             = 0x4a,
-       EXPROM_ADDR             = 0x4c, /* Unused */
-       EXPROM_DATA             = 0x50, /* Unused */
-       WAKE_EVENT              = 0x51, /* Unused */
-       COUNTDOWN               = 0x54, /* Unused */
-       INT_STATUS_ACK          = 0x5a,
-       INT_ENABLE              = 0x5c,
-       INT_STATUS              = 0x5e, /* Unused */
-       TX_STATUS               = 0x60,
-       MAC_CTRL                = 0x6c,
-       VLAN_TAG                = 0x70, /* Unused */
-       PHY_SET                 = 0x75,
-       PHY_CTRL                = 0x76,
-       STATION_ADDRESS_0       = 0x78,
-       STATION_ADDRESS_1       = 0x7a,
-       STATION_ADDRESS_2       = 0x7c,
-       MAX_FRAME_SIZE          = 0x86,
-       RECEIVE_MODE            = 0x88,
-       HASHTABLE_0             = 0x8c,
-       HASHTABLE_1             = 0x90,
-       RMON_STATISTICS_MASK    = 0x98,
-       STATISTICS_MASK         = 0x9c,
-       RX_JUMBO_FRAMES         = 0xbc, /* Unused */
-       TCP_CHECKSUM_ERRORS     = 0xc0, /* Unused */
-       IP_CHECKSUM_ERRORS      = 0xc2, /* Unused */
-       UDP_CHECKSUM_ERRORS     = 0xc4, /* Unused */
-       TX_JUMBO_FRAMES         = 0xf4  /* Unused */
-};
-
-/* Ethernet MIB statistic register offsets. */
-#define        IPG_OCTETRCVOK                  0xA8
-#define        IPG_MCSTOCTETRCVDOK             0xAC
-#define        IPG_BCSTOCTETRCVOK              0xB0
-#define        IPG_FRAMESRCVDOK                0xB4
-#define        IPG_MCSTFRAMESRCVDOK            0xB8
-#define        IPG_BCSTFRAMESRCVDOK            0xBE
-#define        IPG_MACCONTROLFRAMESRCVD        0xC6
-#define        IPG_FRAMETOOLONGERRORS          0xC8
-#define        IPG_INRANGELENGTHERRORS         0xCA
-#define        IPG_FRAMECHECKSEQERRORS         0xCC
-#define        IPG_FRAMESLOSTRXERRORS          0xCE
-#define        IPG_OCTETXMTOK                  0xD0
-#define        IPG_MCSTOCTETXMTOK              0xD4
-#define        IPG_BCSTOCTETXMTOK              0xD8
-#define        IPG_FRAMESXMTDOK                0xDC
-#define        IPG_MCSTFRAMESXMTDOK            0xE0
-#define        IPG_FRAMESWDEFERREDXMT          0xE4
-#define        IPG_LATECOLLISIONS              0xE8
-#define        IPG_MULTICOLFRAMES              0xEC
-#define        IPG_SINGLECOLFRAMES             0xF0
-#define        IPG_BCSTFRAMESXMTDOK            0xF6
-#define        IPG_CARRIERSENSEERRORS          0xF8
-#define        IPG_MACCONTROLFRAMESXMTDOK      0xFA
-#define        IPG_FRAMESABORTXSCOLLS          0xFC
-#define        IPG_FRAMESWEXDEFERRAL           0xFE
-
-/* RMON statistic register offsets. */
-#define        IPG_ETHERSTATSCOLLISIONS                        0x100
-#define        IPG_ETHERSTATSOCTETSTRANSMIT                    0x104
-#define        IPG_ETHERSTATSPKTSTRANSMIT                      0x108
-#define        IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT             0x10C
-#define        IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT        0x110
-#define        IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT       0x114
-#define        IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT       0x118
-#define        IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT      0x11C
-#define        IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT     0x120
-#define        IPG_ETHERSTATSCRCALIGNERRORS                    0x124
-#define        IPG_ETHERSTATSUNDERSIZEPKTS                     0x128
-#define        IPG_ETHERSTATSFRAGMENTS                         0x12C
-#define        IPG_ETHERSTATSJABBERS                           0x130
-#define        IPG_ETHERSTATSOCTETS                            0x134
-#define        IPG_ETHERSTATSPKTS                              0x138
-#define        IPG_ETHERSTATSPKTS64OCTESTS                     0x13C
-#define        IPG_ETHERSTATSPKTS65TO127OCTESTS                0x140
-#define        IPG_ETHERSTATSPKTS128TO255OCTESTS               0x144
-#define        IPG_ETHERSTATSPKTS256TO511OCTESTS               0x148
-#define        IPG_ETHERSTATSPKTS512TO1023OCTESTS              0x14C
-#define        IPG_ETHERSTATSPKTS1024TO1518OCTESTS             0x150
-
-/* RMON statistic register equivalents. */
-#define        IPG_ETHERSTATSMULTICASTPKTSTRANSMIT             0xE0
-#define        IPG_ETHERSTATSBROADCASTPKTSTRANSMIT             0xF6
-#define        IPG_ETHERSTATSMULTICASTPKTS                     0xB8
-#define        IPG_ETHERSTATSBROADCASTPKTS                     0xBE
-#define        IPG_ETHERSTATSOVERSIZEPKTS                      0xC8
-#define        IPG_ETHERSTATSDROPEVENTS                        0xCE
-
-/* Serial EEPROM offsets */
-#define        IPG_EEPROM_CONFIGPARAM          0x00
-#define        IPG_EEPROM_ASICCTRL             0x01
-#define        IPG_EEPROM_SUBSYSTEMVENDORID    0x02
-#define        IPG_EEPROM_SUBSYSTEMID          0x03
-#define        IPG_EEPROM_STATIONADDRESS0      0x10
-#define        IPG_EEPROM_STATIONADDRESS1      0x11
-#define        IPG_EEPROM_STATIONADDRESS2      0x12
-
-/* Register & data structure bit masks */
-
-/* PCI register masks. */
-
-/* IOBaseAddress */
-#define         IPG_PIB_RSVD_MASK              0xFFFFFE01
-#define         IPG_PIB_IOBASEADDRESS          0xFFFFFF00
-#define         IPG_PIB_IOBASEADDRIND          0x00000001
-
-/* MemBaseAddress */
-#define         IPG_PMB_RSVD_MASK              0xFFFFFE07
-#define         IPG_PMB_MEMBASEADDRIND         0x00000001
-#define         IPG_PMB_MEMMAPTYPE             0x00000006
-#define         IPG_PMB_MEMMAPTYPE0            0x00000002
-#define         IPG_PMB_MEMMAPTYPE1            0x00000004
-#define         IPG_PMB_MEMBASEADDRESS         0xFFFFFE00
-
-/* ConfigStatus */
-#define IPG_CS_RSVD_MASK                0xFFB0
-#define IPG_CS_CAPABILITIES             0x0010
-#define IPG_CS_66MHZCAPABLE             0x0020
-#define IPG_CS_FASTBACK2BACK            0x0080
-#define IPG_CS_DATAPARITYREPORTED       0x0100
-#define IPG_CS_DEVSELTIMING             0x0600
-#define IPG_CS_SIGNALEDTARGETABORT      0x0800
-#define IPG_CS_RECEIVEDTARGETABORT      0x1000
-#define IPG_CS_RECEIVEDMASTERABORT      0x2000
-#define IPG_CS_SIGNALEDSYSTEMERROR      0x4000
-#define IPG_CS_DETECTEDPARITYERROR      0x8000
-
-/* TFD data structure masks. */
-
-/* TFDList, TFC */
-#define        IPG_TFC_RSVD_MASK                       0x0000FFFF9FFFFFFFULL
-#define        IPG_TFC_FRAMEID                         0x000000000000FFFFULL
-#define        IPG_TFC_WORDALIGN                       0x0000000000030000ULL
-#define        IPG_TFC_WORDALIGNTODWORD                0x0000000000000000ULL
-#define        IPG_TFC_WORDALIGNTOWORD                 0x0000000000020000ULL
-#define        IPG_TFC_WORDALIGNDISABLED               0x0000000000030000ULL
-#define        IPG_TFC_TCPCHECKSUMENABLE               0x0000000000040000ULL
-#define        IPG_TFC_UDPCHECKSUMENABLE               0x0000000000080000ULL
-#define        IPG_TFC_IPCHECKSUMENABLE                0x0000000000100000ULL
-#define        IPG_TFC_FCSAPPENDDISABLE                0x0000000000200000ULL
-#define        IPG_TFC_TXINDICATE                      0x0000000000400000ULL
-#define        IPG_TFC_TXDMAINDICATE                   0x0000000000800000ULL
-#define        IPG_TFC_FRAGCOUNT                       0x000000000F000000ULL
-#define        IPG_TFC_VLANTAGINSERT                   0x0000000010000000ULL
-#define        IPG_TFC_TFDDONE                         0x0000000080000000ULL
-#define        IPG_TFC_VID                             0x00000FFF00000000ULL
-#define        IPG_TFC_CFI                             0x0000100000000000ULL
-#define        IPG_TFC_USERPRIORITY                    0x0000E00000000000ULL
-
-/* TFDList, FragInfo */
-#define        IPG_TFI_RSVD_MASK                       0xFFFF00FFFFFFFFFFULL
-#define        IPG_TFI_FRAGADDR                        0x000000FFFFFFFFFFULL
-#define        IPG_TFI_FRAGLEN                         0xFFFF000000000000ULL
-
-/* RFD data structure masks. */
-
-/* RFDList, RFS */
-#define        IPG_RFS_RSVD_MASK                       0x0000FFFFFFFFFFFFULL
-#define        IPG_RFS_RXFRAMELEN                      0x000000000000FFFFULL
-#define        IPG_RFS_RXFIFOOVERRUN                   0x0000000000010000ULL
-#define        IPG_RFS_RXRUNTFRAME                     0x0000000000020000ULL
-#define        IPG_RFS_RXALIGNMENTERROR                0x0000000000040000ULL
-#define        IPG_RFS_RXFCSERROR                      0x0000000000080000ULL
-#define        IPG_RFS_RXOVERSIZEDFRAME                0x0000000000100000ULL
-#define        IPG_RFS_RXLENGTHERROR                   0x0000000000200000ULL
-#define        IPG_RFS_VLANDETECTED                    0x0000000000400000ULL
-#define        IPG_RFS_TCPDETECTED                     0x0000000000800000ULL
-#define        IPG_RFS_TCPERROR                        0x0000000001000000ULL
-#define        IPG_RFS_UDPDETECTED                     0x0000000002000000ULL
-#define        IPG_RFS_UDPERROR                        0x0000000004000000ULL
-#define        IPG_RFS_IPDETECTED                      0x0000000008000000ULL
-#define        IPG_RFS_IPERROR                         0x0000000010000000ULL
-#define        IPG_RFS_FRAMESTART                      0x0000000020000000ULL
-#define        IPG_RFS_FRAMEEND                        0x0000000040000000ULL
-#define        IPG_RFS_RFDDONE                         0x0000000080000000ULL
-#define        IPG_RFS_TCI                             0x0000FFFF00000000ULL
-
-/* RFDList, FragInfo */
-#define        IPG_RFI_RSVD_MASK                       0xFFFF00FFFFFFFFFFULL
-#define        IPG_RFI_FRAGADDR                        0x000000FFFFFFFFFFULL
-#define        IPG_RFI_FRAGLEN                         0xFFFF000000000000ULL
-
-/* I/O Register masks. */
-
-/* RMON Statistics Mask */
-#define        IPG_RZ_ALL                                      0x0FFFFFFF
-
-/* Statistics Mask */
-#define        IPG_SM_ALL                                      0x0FFFFFFF
-#define        IPG_SM_OCTETRCVOK_FRAMESRCVDOK                  0x00000001
-#define        IPG_SM_MCSTOCTETRCVDOK_MCSTFRAMESRCVDOK         0x00000002
-#define        IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK         0x00000004
-#define        IPG_SM_RXJUMBOFRAMES                            0x00000008
-#define        IPG_SM_TCPCHECKSUMERRORS                        0x00000010
-#define        IPG_SM_IPCHECKSUMERRORS                         0x00000020
-#define        IPG_SM_UDPCHECKSUMERRORS                        0x00000040
-#define        IPG_SM_MACCONTROLFRAMESRCVD                     0x00000080
-#define        IPG_SM_FRAMESTOOLONGERRORS                      0x00000100
-#define        IPG_SM_INRANGELENGTHERRORS                      0x00000200
-#define        IPG_SM_FRAMECHECKSEQERRORS                      0x00000400
-#define        IPG_SM_FRAMESLOSTRXERRORS                       0x00000800
-#define        IPG_SM_OCTETXMTOK_FRAMESXMTOK                   0x00001000
-#define        IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK          0x00002000
-#define        IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK          0x00004000
-#define        IPG_SM_FRAMESWDEFERREDXMT                       0x00008000
-#define        IPG_SM_LATECOLLISIONS                           0x00010000
-#define        IPG_SM_MULTICOLFRAMES                           0x00020000
-#define        IPG_SM_SINGLECOLFRAMES                          0x00040000
-#define        IPG_SM_TXJUMBOFRAMES                            0x00080000
-#define        IPG_SM_CARRIERSENSEERRORS                       0x00100000
-#define        IPG_SM_MACCONTROLFRAMESXMTD                     0x00200000
-#define        IPG_SM_FRAMESABORTXSCOLLS                       0x00400000
-#define        IPG_SM_FRAMESWEXDEFERAL                         0x00800000
-
-/* Countdown */
-#define        IPG_CD_RSVD_MASK                0x0700FFFF
-#define        IPG_CD_COUNT                    0x0000FFFF
-#define        IPG_CD_COUNTDOWNSPEED           0x01000000
-#define        IPG_CD_COUNTDOWNMODE            0x02000000
-#define        IPG_CD_COUNTINTENABLED          0x04000000
-
-/* TxDMABurstThresh */
-#define IPG_TB_RSVD_MASK                0xFF
-
-/* TxDMAUrgentThresh */
-#define IPG_TU_RSVD_MASK                0xFF
-
-/* TxDMAPollPeriod */
-#define IPG_TP_RSVD_MASK                0xFF
-
-/* RxDMAUrgentThresh */
-#define IPG_RU_RSVD_MASK                0xFF
-
-/* RxDMAPollPeriod */
-#define IPG_RP_RSVD_MASK                0xFF
-
-/* ReceiveMode */
-#define IPG_RM_RSVD_MASK                0x3F
-#define IPG_RM_RECEIVEUNICAST           0x01
-#define IPG_RM_RECEIVEMULTICAST         0x02
-#define IPG_RM_RECEIVEBROADCAST         0x04
-#define IPG_RM_RECEIVEALLFRAMES         0x08
-#define IPG_RM_RECEIVEMULTICASTHASH     0x10
-#define IPG_RM_RECEIVEIPMULTICAST       0x20
-
-/* PhySet */
-#define IPG_PS_MEM_LENB9B               0x01
-#define IPG_PS_MEM_LEN9                 0x02
-#define IPG_PS_NON_COMPDET              0x04
-
-/* PhyCtrl */
-#define IPG_PC_RSVD_MASK                0xFF
-#define IPG_PC_MGMTCLK_LO               0x00
-#define IPG_PC_MGMTCLK_HI               0x01
-#define IPG_PC_MGMTCLK                  0x01
-#define IPG_PC_MGMTDATA                 0x02
-#define IPG_PC_MGMTDIR                  0x04
-#define IPG_PC_DUPLEX_POLARITY          0x08
-#define IPG_PC_DUPLEX_STATUS            0x10
-#define IPG_PC_LINK_POLARITY            0x20
-#define IPG_PC_LINK_SPEED               0xC0
-#define IPG_PC_LINK_SPEED_10MBPS        0x40
-#define IPG_PC_LINK_SPEED_100MBPS       0x80
-#define IPG_PC_LINK_SPEED_1000MBPS      0xC0
-
-/* DMACtrl */
-#define IPG_DC_RSVD_MASK                0xC07D9818
-#define IPG_DC_RX_DMA_COMPLETE          0x00000008
-#define IPG_DC_RX_DMA_POLL_NOW          0x00000010
-#define IPG_DC_TX_DMA_COMPLETE          0x00000800
-#define IPG_DC_TX_DMA_POLL_NOW          0x00001000
-#define IPG_DC_TX_DMA_IN_PROG           0x00008000
-#define IPG_DC_RX_EARLY_DISABLE         0x00010000
-#define IPG_DC_MWI_DISABLE              0x00040000
-#define IPG_DC_TX_WRITE_BACK_DISABLE    0x00080000
-#define IPG_DC_TX_BURST_LIMIT           0x00700000
-#define IPG_DC_TARGET_ABORT             0x40000000
-#define IPG_DC_MASTER_ABORT             0x80000000
-
-/* ASICCtrl */
-#define IPG_AC_RSVD_MASK                0x07FFEFF2
-#define IPG_AC_EXP_ROM_SIZE             0x00000002
-#define IPG_AC_PHY_SPEED10              0x00000010
-#define IPG_AC_PHY_SPEED100             0x00000020
-#define IPG_AC_PHY_SPEED1000            0x00000040
-#define IPG_AC_PHY_MEDIA                0x00000080
-#define IPG_AC_FORCED_CFG               0x00000700
-#define IPG_AC_D3RESETDISABLE           0x00000800
-#define IPG_AC_SPEED_UP_MODE            0x00002000
-#define IPG_AC_LED_MODE                 0x00004000
-#define IPG_AC_RST_OUT_POLARITY         0x00008000
-#define IPG_AC_GLOBAL_RESET             0x00010000
-#define IPG_AC_RX_RESET                 0x00020000
-#define IPG_AC_TX_RESET                 0x00040000
-#define IPG_AC_DMA                      0x00080000
-#define IPG_AC_FIFO                     0x00100000
-#define IPG_AC_NETWORK                  0x00200000
-#define IPG_AC_HOST                     0x00400000
-#define IPG_AC_AUTO_INIT                0x00800000
-#define IPG_AC_RST_OUT                  0x01000000
-#define IPG_AC_INT_REQUEST              0x02000000
-#define IPG_AC_RESET_BUSY               0x04000000
-#define IPG_AC_LED_SPEED                0x08000000
-#define IPG_AC_LED_MODE_BIT_1           0x20000000
-
-/* EepromCtrl */
-#define IPG_EC_RSVD_MASK                0x83FF
-#define IPG_EC_EEPROM_ADDR              0x00FF
-#define IPG_EC_EEPROM_OPCODE            0x0300
-#define IPG_EC_EEPROM_SUBCOMMAD         0x0000
-#define IPG_EC_EEPROM_WRITEOPCODE       0x0100
-#define IPG_EC_EEPROM_READOPCODE        0x0200
-#define IPG_EC_EEPROM_ERASEOPCODE       0x0300
-#define IPG_EC_EEPROM_BUSY              0x8000
-
-/* FIFOCtrl */
-#define IPG_FC_RSVD_MASK                0xC001
-#define IPG_FC_RAM_TEST_MODE            0x0001
-#define IPG_FC_TRANSMITTING             0x4000
-#define IPG_FC_RECEIVING                0x8000
-
-/* TxStatus */
-#define IPG_TS_RSVD_MASK                0xFFFF00DD
-#define IPG_TS_TX_ERROR                 0x00000001
-#define IPG_TS_LATE_COLLISION           0x00000004
-#define IPG_TS_TX_MAX_COLL              0x00000008
-#define IPG_TS_TX_UNDERRUN              0x00000010
-#define IPG_TS_TX_IND_REQD              0x00000040
-#define IPG_TS_TX_COMPLETE              0x00000080
-#define IPG_TS_TX_FRAMEID               0xFFFF0000
-
-/* WakeEvent */
-#define IPG_WE_WAKE_PKT_ENABLE          0x01
-#define IPG_WE_MAGIC_PKT_ENABLE         0x02
-#define IPG_WE_LINK_EVT_ENABLE          0x04
-#define IPG_WE_WAKE_POLARITY            0x08
-#define IPG_WE_WAKE_PKT_EVT             0x10
-#define IPG_WE_MAGIC_PKT_EVT            0x20
-#define IPG_WE_LINK_EVT                 0x40
-#define IPG_WE_WOL_ENABLE               0x80
-
-/* IntEnable */
-#define IPG_IE_RSVD_MASK                0x1FFE
-#define IPG_IE_HOST_ERROR               0x0002
-#define IPG_IE_TX_COMPLETE              0x0004
-#define IPG_IE_MAC_CTRL_FRAME           0x0008
-#define IPG_IE_RX_COMPLETE              0x0010
-#define IPG_IE_RX_EARLY                 0x0020
-#define IPG_IE_INT_REQUESTED            0x0040
-#define IPG_IE_UPDATE_STATS             0x0080
-#define IPG_IE_LINK_EVENT               0x0100
-#define IPG_IE_TX_DMA_COMPLETE          0x0200
-#define IPG_IE_RX_DMA_COMPLETE          0x0400
-#define IPG_IE_RFD_LIST_END             0x0800
-#define IPG_IE_RX_DMA_PRIORITY          0x1000
-
-/* IntStatus */
-#define IPG_IS_RSVD_MASK                0x1FFF
-#define IPG_IS_INTERRUPT_STATUS         0x0001
-#define IPG_IS_HOST_ERROR               0x0002
-#define IPG_IS_TX_COMPLETE              0x0004
-#define IPG_IS_MAC_CTRL_FRAME           0x0008
-#define IPG_IS_RX_COMPLETE              0x0010
-#define IPG_IS_RX_EARLY                 0x0020
-#define IPG_IS_INT_REQUESTED            0x0040
-#define IPG_IS_UPDATE_STATS             0x0080
-#define IPG_IS_LINK_EVENT               0x0100
-#define IPG_IS_TX_DMA_COMPLETE          0x0200
-#define IPG_IS_RX_DMA_COMPLETE          0x0400
-#define IPG_IS_RFD_LIST_END             0x0800
-#define IPG_IS_RX_DMA_PRIORITY          0x1000
-
-/* MACCtrl */
-#define IPG_MC_RSVD_MASK                0x7FE33FA3
-#define IPG_MC_IFS_SELECT               0x00000003
-#define IPG_MC_IFS_4352BIT              0x00000003
-#define IPG_MC_IFS_1792BIT              0x00000002
-#define IPG_MC_IFS_1024BIT              0x00000001
-#define IPG_MC_IFS_96BIT                0x00000000
-#define IPG_MC_DUPLEX_SELECT            0x00000020
-#define IPG_MC_DUPLEX_SELECT_FD         0x00000020
-#define IPG_MC_DUPLEX_SELECT_HD         0x00000000
-#define IPG_MC_TX_FLOW_CONTROL_ENABLE   0x00000080
-#define IPG_MC_RX_FLOW_CONTROL_ENABLE   0x00000100
-#define IPG_MC_RCV_FCS                  0x00000200
-#define IPG_MC_FIFO_LOOPBACK            0x00000400
-#define IPG_MC_MAC_LOOPBACK             0x00000800
-#define IPG_MC_AUTO_VLAN_TAGGING        0x00001000
-#define IPG_MC_AUTO_VLAN_UNTAGGING      0x00002000
-#define IPG_MC_COLLISION_DETECT         0x00010000
-#define IPG_MC_CARRIER_SENSE            0x00020000
-#define IPG_MC_STATISTICS_ENABLE        0x00200000
-#define IPG_MC_STATISTICS_DISABLE       0x00400000
-#define IPG_MC_STATISTICS_ENABLED       0x00800000
-#define IPG_MC_TX_ENABLE                0x01000000
-#define IPG_MC_TX_DISABLE               0x02000000
-#define IPG_MC_TX_ENABLED               0x04000000
-#define IPG_MC_RX_ENABLE                0x08000000
-#define IPG_MC_RX_DISABLE               0x10000000
-#define IPG_MC_RX_ENABLED               0x20000000
-#define IPG_MC_PAUSED                   0x40000000
-
-/*
- *     Tune
- */
-
-/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS append on TX. */
-#define         IPG_APPEND_FCS_ON_TX         1
-
-/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS strip on RX. */
-#define         IPG_STRIP_FCS_ON_RX          1
-
-/* Assign IPG_DROP_ON_RX_ETH_ERRORS > 0 to drop RX frames with
- * Ethernet errors.
- */
-#define         IPG_DROP_ON_RX_ETH_ERRORS    1
-
-/* Assign IPG_INSERT_MANUAL_VLAN_TAG > 0 to insert VLAN tags manually
- * (via TFC).
- */
-#define                IPG_INSERT_MANUAL_VLAN_TAG   0
-
-/* Assign IPG_ADD_IPCHECKSUM_ON_TX > 0 for auto IP checksum on TX. */
-#define         IPG_ADD_IPCHECKSUM_ON_TX     0
-
-/* Assign IPG_ADD_TCPCHECKSUM_ON_TX > 0 for auto TCP checksum on TX.
- * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER.
- */
-#define         IPG_ADD_TCPCHECKSUM_ON_TX    0
-
-/* Assign IPG_ADD_UDPCHECKSUM_ON_TX > 0 for auto UDP checksum on TX.
- * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER.
- */
-#define         IPG_ADD_UDPCHECKSUM_ON_TX    0
-
-/* If inserting VLAN tags manually, assign the IPG_MANUAL_VLAN_xx
- * constants as desired.
- */
-#define                IPG_MANUAL_VLAN_VID             0xABC
-#define                IPG_MANUAL_VLAN_CFI             0x1
-#define                IPG_MANUAL_VLAN_USERPRIORITY 0x5
-
-#define         IPG_IO_REG_RANGE               0xFF
-#define         IPG_MEM_REG_RANGE              0x154
-#define         IPG_DRIVER_NAME                "Sundance Technology IPG Triple-Speed Ethernet"
-#define         IPG_NIC_PHY_ADDRESS          0x01
-#define                IPG_DMALIST_ALIGN_PAD   0x07
-#define                IPG_MULTICAST_HASHTABLE_SIZE    0x40
-
-/* Number of milliseconds to wait after issuing a software reset.
- * 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation.
- */
-#define         IPG_AC_RESETWAIT             0x05
-
-/* Number of IPG_AC_RESETWAIT timeperiods before declaring timeout. */
-#define         IPG_AC_RESET_TIMEOUT         0x0A
-
-/* Minimum number of nanoseconds used to toggle MDC clock during
- * MII/GMII register access.
- */
-#define                IPG_PC_PHYCTRLWAIT_NS           200
-
-#define                IPG_TFDLIST_LENGTH              0x100
-
-/* Number of frames between TxDMAComplete interrupt.
- * 0 < IPG_FRAMESBETWEENTXDMACOMPLETES <= IPG_TFDLIST_LENGTH
- */
-#define                IPG_FRAMESBETWEENTXDMACOMPLETES 0x1
-
-#define                IPG_RFDLIST_LENGTH              0x100
-
-/* Maximum number of RFDs to process per interrupt.
- * 1 < IPG_MAXRFDPROCESS_COUNT < IPG_RFDLIST_LENGTH
- */
-#define                IPG_MAXRFDPROCESS_COUNT 0x80
-
-/* Minimum margin between last freed RFD, and current RFD.
- * 1 < IPG_MINUSEDRFDSTOFREE < IPG_RFDLIST_LENGTH
- */
-#define                IPG_MINUSEDRFDSTOFREE   0x80
-
-/* specify the jumbo frame maximum size
- * per unit is 0x600 (the rx_buffer size that one RFD can carry)
- */
-#define     MAX_JUMBOSIZE              0x8     /* max is 12K */
-
-/* Key register values loaded at driver start up. */
-
-/* TXDMAPollPeriod is specified in 320ns increments.
- *
- * Value       Time
- * ---------------------
- * 0x00-0x01   320ns
- * 0x03                ~1us
- * 0x1F                ~10us
- * 0xFF                ~82us
- */
-#define                IPG_TXDMAPOLLPERIOD_VALUE       0x26
-
-/* TxDMAUrgentThresh specifies the minimum amount of
- * data in the transmit FIFO before asserting an
- * urgent transmit DMA request.
- *
- * Value       Min TxFIFO occupied space before urgent TX request
- * ---------------------------------------------------------------
- * 0x00-0x04   128 bytes (1024 bits)
- * 0x27                1248 bytes (~10000 bits)
- * 0x30                1536 bytes (12288 bits)
- * 0xFF                8192 bytes (65535 bits)
- */
-#define                IPG_TXDMAURGENTTHRESH_VALUE     0x04
-
-/* TxDMABurstThresh specifies the minimum amount of
- * free space in the transmit FIFO before asserting an
- * transmit DMA request.
- *
- * Value       Min TxFIFO free space before TX request
- * ----------------------------------------------------
- * 0x00-0x08   256 bytes
- * 0x30                1536 bytes
- * 0xFF                8192 bytes
- */
-#define                IPG_TXDMABURSTTHRESH_VALUE      0x30
-
-/* RXDMAPollPeriod is specified in 320ns increments.
- *
- * Value       Time
- * ---------------------
- * 0x00-0x01   320ns
- * 0x03                ~1us
- * 0x1F                ~10us
- * 0xFF                ~82us
- */
-#define                IPG_RXDMAPOLLPERIOD_VALUE       0x01
-
-/* RxDMAUrgentThresh specifies the minimum amount of
- * free space within the receive FIFO before asserting
- * a urgent receive DMA request.
- *
- * Value       Min RxFIFO free space before urgent RX request
- * ---------------------------------------------------------------
- * 0x00-0x04   128 bytes (1024 bits)
- * 0x27                1248 bytes (~10000 bits)
- * 0x30                1536 bytes (12288 bits)
- * 0xFF                8192 bytes (65535 bits)
- */
-#define                IPG_RXDMAURGENTTHRESH_VALUE     0x30
-
-/* RxDMABurstThresh specifies the minimum amount of
- * occupied space within the receive FIFO before asserting
- * a receive DMA request.
- *
- * Value       Min TxFIFO free space before TX request
- * ----------------------------------------------------
- * 0x00-0x08   256 bytes
- * 0x30                1536 bytes
- * 0xFF                8192 bytes
- */
-#define                IPG_RXDMABURSTTHRESH_VALUE      0x30
-
-/* FlowOnThresh specifies the maximum amount of occupied
- * space in the receive FIFO before a PAUSE frame with
- * maximum pause time transmitted.
- *
- * Value       Max RxFIFO occupied space before PAUSE
- * ---------------------------------------------------
- * 0x0000      0 bytes
- * 0x0740      29,696 bytes
- * 0x07FF      32,752 bytes
- */
-#define                IPG_FLOWONTHRESH_VALUE  0x0740
-
-/* FlowOffThresh specifies the minimum amount of occupied
- * space in the receive FIFO before a PAUSE frame with
- * zero pause time is transmitted.
- *
- * Value       Max RxFIFO occupied space before PAUSE
- * ---------------------------------------------------
- * 0x0000      0 bytes
- * 0x00BF      3056 bytes
- * 0x07FF      32,752 bytes
- */
-#define                IPG_FLOWOFFTHRESH_VALUE 0x00BF
-
-/*
- * Miscellaneous macros.
- */
-
-/* Macros for printing debug statements. */
-#ifdef IPG_DEBUG
-#  define IPG_DEBUG_MSG(fmt, args...)                  \
-do {                                                   \
-       if (0)                                          \
-               printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-#  define IPG_DDEBUG_MSG(fmt, args...)                 \
-       printk(KERN_DEBUG "IPG: " fmt, ##args)
-#  define IPG_DUMPRFDLIST(args) ipg_dump_rfdlist(args)
-#  define IPG_DUMPTFDLIST(args) ipg_dump_tfdlist(args)
-#else
-#  define IPG_DEBUG_MSG(fmt, args...)                  \
-do {                                                   \
-       if (0)                                          \
-               printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-#  define IPG_DDEBUG_MSG(fmt, args...)                 \
-do {                                                   \
-       if (0)                                          \
-               printk(KERN_DEBUG "IPG: " fmt, ##args); \
-} while (0)
-#  define IPG_DUMPRFDLIST(args)
-#  define IPG_DUMPTFDLIST(args)
-#endif
-
-/*
- * End miscellaneous macros.
- */
-
-/* Transmit Frame Descriptor. The IPG supports 15 fragments,
- * however Linux requires only a single fragment. Note, each
- * TFD field is 64 bits wide.
- */
-struct ipg_tx {
-       __le64 next_desc;
-       __le64 tfc;
-       __le64 frag_info;
-};
-
-/* Receive Frame Descriptor. Note, each RFD field is 64 bits wide.
- */
-struct ipg_rx {
-       __le64 next_desc;
-       __le64 rfs;
-       __le64 frag_info;
-};
-
-struct ipg_jumbo {
-       int found_start;
-       int current_size;
-       struct sk_buff *skb;
-};
-
-/* Structure of IPG NIC specific data. */
-struct ipg_nic_private {
-       void __iomem *ioaddr;
-       struct ipg_tx *txd;
-       struct ipg_rx *rxd;
-       dma_addr_t txd_map;
-       dma_addr_t rxd_map;
-       struct sk_buff *tx_buff[IPG_TFDLIST_LENGTH];
-       struct sk_buff *rx_buff[IPG_RFDLIST_LENGTH];
-       unsigned int tx_current;
-       unsigned int tx_dirty;
-       unsigned int rx_current;
-       unsigned int rx_dirty;
-       bool is_jumbo;
-       struct ipg_jumbo jumbo;
-       unsigned long rxfrag_size;
-       unsigned long rxsupport_size;
-       unsigned long max_rxframe_size;
-       unsigned int rx_buf_sz;
-       struct pci_dev *pdev;
-       struct net_device *dev;
-       struct net_device_stats stats;
-       spinlock_t lock;
-       int tenmbpsmode;
-
-       u16 led_mode;
-       u16 station_addr[3];    /* Station Address in EEPROM Reg 0x10..0x12 */
-
-       struct mutex            mii_mutex;
-       struct mii_if_info      mii_if;
-       int reset_current_tfd;
-#ifdef IPG_DEBUG
-       int RFDlistendCount;
-       int RFDListCheckedCount;
-       int EmptyRFDListCount;
-#endif
-       struct delayed_work task;
-};
-
-#endif                         /* __LINUX_IPG_H */
index 85f1b1e7e505727bcdb7f424348d9dce0c5825d3..31c491e02e69f15187a89e5a399bfc67e2693237 100644 (file)
@@ -892,9 +892,10 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                dev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn;
                dev->caps.port_mask[i] = dev->caps.port_type[i];
                dev->caps.phys_port_id[i] = func_cap.phys_port_id;
-               if (mlx4_get_slave_pkey_gid_tbl_len(dev, i,
-                                                   &dev->caps.gid_table_len[i],
-                                                   &dev->caps.pkey_table_len[i]))
+               err = mlx4_get_slave_pkey_gid_tbl_len(dev, i,
+                                                     &dev->caps.gid_table_len[i],
+                                                     &dev->caps.pkey_table_len[i]);
+               if (err)
                        goto err_mem;
        }
 
@@ -906,6 +907,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                         dev->caps.uar_page_size * dev->caps.num_uars,
                         (unsigned long long)
                         pci_resource_len(dev->persist->pdev, 2));
+               err = -ENOMEM;
                goto err_mem;
        }
 
index 9813d34f3e5b78e0b3d4a99e253b710278bc7171..6fec3e993d020e34fb2995a221baeac7c25126c6 100644 (file)
@@ -4952,26 +4952,41 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave)
        struct res_counter *counter;
        struct res_counter *tmp;
        int err;
-       int index;
+       int *counters_arr = NULL;
+       int i, j;
 
        err = move_all_busy(dev, slave, RES_COUNTER);
        if (err)
                mlx4_warn(dev, "rem_slave_counters: Could not move all counters - too busy for slave %d\n",
                          slave);
 
-       spin_lock_irq(mlx4_tlock(dev));
-       list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
-               if (counter->com.owner == slave) {
-                       index = counter->com.res_id;
-                       rb_erase(&counter->com.node,
-                                &tracker->res_tree[RES_COUNTER]);
-                       list_del(&counter->com.list);
-                       kfree(counter);
-                       __mlx4_counter_free(dev, index);
+       counters_arr = kmalloc_array(dev->caps.max_counters,
+                                    sizeof(*counters_arr), GFP_KERNEL);
+       if (!counters_arr)
+               return;
+
+       do {
+               i = 0;
+               j = 0;
+               spin_lock_irq(mlx4_tlock(dev));
+               list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
+                       if (counter->com.owner == slave) {
+                               counters_arr[i++] = counter->com.res_id;
+                               rb_erase(&counter->com.node,
+                                        &tracker->res_tree[RES_COUNTER]);
+                               list_del(&counter->com.list);
+                               kfree(counter);
+                       }
+               }
+               spin_unlock_irq(mlx4_tlock(dev));
+
+               while (j < i) {
+                       __mlx4_counter_free(dev, counters_arr[j++]);
                        mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
                }
-       }
-       spin_unlock_irq(mlx4_tlock(dev));
+       } while (i);
+
+       kfree(counters_arr);
 }
 
 static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
index f2ae62dd8c094ac4c11917f29d65fbb63c2194a2..22e72bf1ae4894a846d790d8973b87aee3ac6431 100644 (file)
@@ -334,9 +334,15 @@ struct mlx5e_tx_skb_cb {
 
 #define MLX5E_TX_SKB_CB(__skb) ((struct mlx5e_tx_skb_cb *)__skb->cb)
 
+enum mlx5e_dma_map_type {
+       MLX5E_DMA_MAP_SINGLE,
+       MLX5E_DMA_MAP_PAGE
+};
+
 struct mlx5e_sq_dma {
-       dma_addr_t addr;
-       u32        size;
+       dma_addr_t              addr;
+       u32                     size;
+       enum mlx5e_dma_map_type type;
 };
 
 enum {
index 5fc4d2d78cdf7525c4f469733ee317ae1f0142ca..1e52db32c73d28bdc5e76f4857522a7b2ecff90b 100644 (file)
@@ -1332,6 +1332,42 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
        return err;
 }
 
+static int mlx5e_refresh_tir_self_loopback_enable(struct mlx5_core_dev *mdev,
+                                                 u32 tirn)
+{
+       void *in;
+       int inlen;
+       int err;
+
+       inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
+       in = mlx5_vzalloc(inlen);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
+
+       err = mlx5_core_modify_tir(mdev, tirn, in, inlen);
+
+       kvfree(in);
+
+       return err;
+}
+
+static int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5e_priv *priv)
+{
+       int err;
+       int i;
+
+       for (i = 0; i < MLX5E_NUM_TT; i++) {
+               err = mlx5e_refresh_tir_self_loopback_enable(priv->mdev,
+                                                            priv->tirn[i]);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static int mlx5e_set_dev_port_mtu(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -1376,6 +1412,13 @@ int mlx5e_open_locked(struct net_device *netdev)
                goto err_clear_state_opened_flag;
        }
 
+       err = mlx5e_refresh_tirs_self_loopback_enable(priv);
+       if (err) {
+               netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
+                          __func__, err);
+               goto err_close_channels;
+       }
+
        mlx5e_update_carrier(priv);
        mlx5e_redirect_rqts(priv);
 
@@ -1383,6 +1426,8 @@ int mlx5e_open_locked(struct net_device *netdev)
 
        return 0;
 
+err_close_channels:
+       mlx5e_close_channels(priv);
 err_clear_state_opened_flag:
        clear_bit(MLX5E_STATE_OPENED, &priv->state);
        return err;
@@ -1856,6 +1901,8 @@ static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
 
        mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
 
+       max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
        if (new_mtu > max_mtu) {
                netdev_err(netdev,
                           "%s: Bad MTU (%d) > (%d) Max\n",
@@ -1909,6 +1956,9 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
                               "Not creating net device, some required device capabilities are missing\n");
                return -ENOTSUPP;
        }
+       if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
+               mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
+
        return 0;
 }
 
index cd8f85a251d7da5509c0651b6ab781ce1d152084..1341b1d3c421d2a0f2050b7c0103853cbecf1cd6 100644 (file)
@@ -61,39 +61,47 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw)
        }
 }
 
-static void mlx5e_dma_pop_last_pushed(struct mlx5e_sq *sq, dma_addr_t *addr,
-                                     u32 *size)
+static inline void mlx5e_tx_dma_unmap(struct device *pdev,
+                                     struct mlx5e_sq_dma *dma)
 {
-       sq->dma_fifo_pc--;
-       *addr = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr;
-       *size = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size;
-}
-
-static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb)
-{
-       dma_addr_t addr;
-       u32 size;
-       int i;
-
-       for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) {
-               mlx5e_dma_pop_last_pushed(sq, &addr, &size);
-               dma_unmap_single(sq->pdev, addr, size, DMA_TO_DEVICE);
+       switch (dma->type) {
+       case MLX5E_DMA_MAP_SINGLE:
+               dma_unmap_single(pdev, dma->addr, dma->size, DMA_TO_DEVICE);
+               break;
+       case MLX5E_DMA_MAP_PAGE:
+               dma_unmap_page(pdev, dma->addr, dma->size, DMA_TO_DEVICE);
+               break;
+       default:
+               WARN_ONCE(true, "mlx5e_tx_dma_unmap unknown DMA type!\n");
        }
 }
 
-static inline void mlx5e_dma_push(struct mlx5e_sq *sq, dma_addr_t addr,
-                                 u32 size)
+static inline void mlx5e_dma_push(struct mlx5e_sq *sq,
+                                 dma_addr_t addr,
+                                 u32 size,
+                                 enum mlx5e_dma_map_type map_type)
 {
        sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr = addr;
        sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size = size;
+       sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].type = map_type;
        sq->dma_fifo_pc++;
 }
 
-static inline void mlx5e_dma_get(struct mlx5e_sq *sq, u32 i, dma_addr_t *addr,
-                                u32 *size)
+static inline struct mlx5e_sq_dma *mlx5e_dma_get(struct mlx5e_sq *sq, u32 i)
 {
-       *addr = sq->dma_fifo[i & sq->dma_fifo_mask].addr;
-       *size = sq->dma_fifo[i & sq->dma_fifo_mask].size;
+       return &sq->dma_fifo[i & sq->dma_fifo_mask];
+}
+
+static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb)
+{
+       int i;
+
+       for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) {
+               struct mlx5e_sq_dma *last_pushed_dma =
+                       mlx5e_dma_get(sq, --sq->dma_fifo_pc);
+
+               mlx5e_tx_dma_unmap(sq->pdev, last_pushed_dma);
+       }
 }
 
 u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -118,8 +126,15 @@ static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq,
         */
 #define MLX5E_MIN_INLINE ETH_HLEN
 
-       if (bf && (skb_headlen(skb) <= sq->max_inline))
-               return skb_headlen(skb);
+       if (bf) {
+               u16 ihs = skb_headlen(skb);
+
+               if (skb_vlan_tag_present(skb))
+                       ihs += VLAN_HLEN;
+
+               if (ihs <= sq->max_inline)
+                       return skb_headlen(skb);
+       }
 
        return MLX5E_MIN_INLINE;
 }
@@ -218,7 +233,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                dseg->lkey       = sq->mkey_be;
                dseg->byte_count = cpu_to_be32(headlen);
 
-               mlx5e_dma_push(sq, dma_addr, headlen);
+               mlx5e_dma_push(sq, dma_addr, headlen, MLX5E_DMA_MAP_SINGLE);
                MLX5E_TX_SKB_CB(skb)->num_dma++;
 
                dseg++;
@@ -237,7 +252,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                dseg->lkey       = sq->mkey_be;
                dseg->byte_count = cpu_to_be32(fsz);
 
-               mlx5e_dma_push(sq, dma_addr, fsz);
+               mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE);
                MLX5E_TX_SKB_CB(skb)->num_dma++;
 
                dseg++;
@@ -353,13 +368,10 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
                        }
 
                        for (j = 0; j < MLX5E_TX_SKB_CB(skb)->num_dma; j++) {
-                               dma_addr_t addr;
-                               u32 size;
+                               struct mlx5e_sq_dma *dma =
+                                       mlx5e_dma_get(sq, dma_fifo_cc++);
 
-                               mlx5e_dma_get(sq, dma_fifo_cc, &addr, &size);
-                               dma_fifo_cc++;
-                               dma_unmap_single(sq->pdev, addr, size,
-                                                DMA_TO_DEVICE);
+                               mlx5e_tx_dma_unmap(sq->pdev, dma);
                        }
 
                        npkts++;
index b4f21232019a98c7e0afd9e5a43a5a160da765fe..79ef799f88ab1fc2518736163c5674aec360c065 100644 (file)
@@ -7429,15 +7429,15 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget
 
                        rtl8169_rx_vlan_tag(desc, skb);
 
+                       if (skb->pkt_type == PACKET_MULTICAST)
+                               dev->stats.multicast++;
+
                        napi_gro_receive(&tp->napi, skb);
 
                        u64_stats_update_begin(&tp->rx_stats.syncp);
                        tp->rx_stats.packets++;
                        tp->rx_stats.bytes += pkt_size;
                        u64_stats_update_end(&tp->rx_stats.syncp);
-
-                       if (skb->pkt_type == PACKET_MULTICAST)
-                               dev->stats.multicast++;
                }
 release_descriptor:
                desc->opts2 = 0;
index aa7b2083cb539c15c8b831e4c0703ab16375a0ae..ee8d1ec61fabaffe081e777d70fd1b381990fbea 100644 (file)
@@ -408,8 +408,6 @@ static int ravb_dmac_init(struct net_device *ndev)
        /* Interrupt enable: */
        /* Frame receive */
        ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
-       /* Receive FIFO full warning */
-       ravb_write(ndev, RIC1_RFWE, RIC1);
        /* Receive FIFO full error, descriptor empty */
        ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
        /* Frame transmitted, timestamp FIFO updated */
@@ -733,8 +731,10 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
                            ((tis  & tic)  & BIT(q))) {
                                if (napi_schedule_prep(&priv->napi[q])) {
                                        /* Mask RX and TX interrupts */
-                                       ravb_write(ndev, ric0 & ~BIT(q), RIC0);
-                                       ravb_write(ndev, tic  & ~BIT(q), TIC);
+                                       ric0 &= ~BIT(q);
+                                       tic &= ~BIT(q);
+                                       ravb_write(ndev, ric0, RIC0);
+                                       ravb_write(ndev, tic, TIC);
                                        __napi_schedule(&priv->napi[q]);
                                } else {
                                        netdev_warn(ndev,
index d288f1c928de611455e44b515972b172340e4686..a3c42a376741f9c86179ca0fae5889203b9f16d5 100644 (file)
@@ -3422,7 +3422,7 @@ static void efx_io_resume(struct pci_dev *pdev)
  * with our request for slot reset the mmio_enabled callback will never be
  * called, and the link_reset callback is not used by AER or EEH mechanisms.
  */
-static struct pci_error_handlers efx_err_handlers = {
+static const struct pci_error_handlers efx_err_handlers = {
        .error_detected = efx_io_error_detected,
        .slot_reset     = efx_io_slot_reset,
        .resume         = efx_io_resume,
index c860c9007e49afda02165733ede46780da58abf3..219a99b7a631d5216c0667e24ca5595b67e56289 100644 (file)
@@ -809,22 +809,17 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata)
 
 static int smsc911x_phy_reset(struct smsc911x_data *pdata)
 {
-       struct phy_device *phy_dev = pdata->phy_dev;
        unsigned int temp;
        unsigned int i = 100000;
 
-       BUG_ON(!phy_dev);
-       BUG_ON(!phy_dev->bus);
-
-       SMSC_TRACE(pdata, hw, "Performing PHY BCR Reset");
-       smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET);
+       temp = smsc911x_reg_read(pdata, PMT_CTRL);
+       smsc911x_reg_write(pdata, PMT_CTRL, temp | PMT_CTRL_PHY_RST_);
        do {
                msleep(1);
-               temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr,
-                       MII_BMCR);
-       } while ((i--) && (temp & BMCR_RESET));
+               temp = smsc911x_reg_read(pdata, PMT_CTRL);
+       } while ((i--) && (temp & PMT_CTRL_PHY_RST_));
 
-       if (temp & BMCR_RESET) {
+       if (unlikely(temp & PMT_CTRL_PHY_RST_)) {
                SMSC_WARN(pdata, hw, "PHY reset failed to complete");
                return -EIO;
        }
@@ -2296,7 +2291,7 @@ static int smsc911x_init(struct net_device *dev)
        }
 
        /* Reset the LAN911x */
-       if (smsc911x_soft_reset(pdata))
+       if (smsc911x_phy_reset(pdata) || smsc911x_soft_reset(pdata))
                return -ENODEV;
 
        dev->flags |= IFF_MULTICAST;
index 9d89bdbf029f4e0ba908bfa8f199514bd3eb026c..82de68b1a45277480e98c2229c82450a61835d2e 100644 (file)
@@ -337,11 +337,11 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
                             QSGMII_PHY_RX_SIGNAL_DETECT_EN |
                             QSGMII_PHY_TX_DRIVER_EN |
                             QSGMII_PHY_QSGMII_EN |
-                            0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
-                            0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
-                            0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
-                            0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
-                            0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
+                            0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
+                            0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET |
+                            0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
+                            0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
+                            0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
        }
 
        plat_dat->has_gmac = true;
index ae68afd50a156199b6f74b2d2e65420cddd02c73..f38696ceee74afcb1aa4eb731e70b3c307e40193 100644 (file)
@@ -345,13 +345,6 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability");
 */
 VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
 
-#define VAL_PKT_LEN_DEF     0
-/* ValPktLen[] is used for setting the checksum offload ability of NIC.
-   0: Receive frame with invalid layer 2 length (Default)
-   1: Drop frame with invalid layer 2 length
-*/
-VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
-
 #define WOL_OPT_DEF     0
 #define WOL_OPT_MIN     0
 #define WOL_OPT_MAX     7
@@ -494,7 +487,6 @@ static void velocity_get_options(struct velocity_opt *opts, int index,
 
        velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);
        velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);
-       velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);
        velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);
        velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);
        opts->numrx = (opts->numrx & ~3);
@@ -2055,8 +2047,9 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
        struct sk_buff *skb;
 
-       if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
-               VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
+       if (unlikely(rd->rdesc0.RSR & (RSR_STP | RSR_EDP | RSR_RL))) {
+               if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP))
+                       VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name);
                stats->rx_length_errors++;
                return -EINVAL;
        }
@@ -2069,17 +2062,6 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
        dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma,
                                    vptr->rx.buf_sz, DMA_FROM_DEVICE);
 
-       /*
-        *      Drop frame not meeting IEEE 802.3
-        */
-
-       if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) {
-               if (rd->rdesc0.RSR & RSR_RL) {
-                       stats->rx_length_errors++;
-                       return -EINVAL;
-               }
-       }
-
        velocity_rx_csum(rd, skb);
 
        if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
index bb8b5304d85117354595d707585613e572ce24c0..b103adb8d62ecfa9c1b21647d5c2498fa9586c96 100644 (file)
@@ -599,7 +599,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid)
                FJES_CMD_REQ_RES_CODE_BUSY) &&
               (timeout > 0)) {
                msleep(200 + hw->my_epid * 20);
-                       timeout -= (200 + hw->my_epid * 20);
+               timeout -= (200 + hw->my_epid * 20);
 
                res_buf->unshare_buffer.length = 0;
                res_buf->unshare_buffer.code = 0;
index d50887e3df6de3b41767ccbb3fb04a67c9d459af..8c48bb2a94ea063aa9dd7c4dc662aa772f34930c 100644 (file)
@@ -254,7 +254,7 @@ void ipvlan_process_multicast(struct work_struct *work)
        }
 }
 
-static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
+static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
                            bool local)
 {
        struct ipvl_dev *ipvlan = addr->master;
@@ -262,6 +262,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
        unsigned int len;
        rx_handler_result_t ret = RX_HANDLER_CONSUMED;
        bool success = false;
+       struct sk_buff *skb = *pskb;
 
        len = skb->len + ETH_HLEN;
        if (unlikely(!(dev->flags & IFF_UP))) {
@@ -273,6 +274,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
        if (!skb)
                goto out;
 
+       *pskb = skb;
        skb->dev = dev;
        skb->pkt_type = PACKET_HOST;
 
@@ -486,7 +488,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
 
        addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
        if (addr)
-               return ipvlan_rcv_frame(addr, skb, true);
+               return ipvlan_rcv_frame(addr, &skb, true);
 
 out:
        skb->dev = ipvlan->phy_dev;
@@ -506,7 +508,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
                if (lyr3h) {
                        addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
                        if (addr)
-                               return ipvlan_rcv_frame(addr, skb, true);
+                               return ipvlan_rcv_frame(addr, &skb, true);
                }
                skb = skb_share_check(skb, GFP_ATOMIC);
                if (!skb)
@@ -589,7 +591,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
 
        addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
        if (addr)
-               ret = ipvlan_rcv_frame(addr, skb, false);
+               ret = ipvlan_rcv_frame(addr, pskb, false);
 
 out:
        return ret;
@@ -626,7 +628,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
 
                addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
                if (addr)
-                       ret = ipvlan_rcv_frame(addr, skb, false);
+                       ret = ipvlan_rcv_frame(addr, pskb, false);
        }
 
        return ret;
@@ -651,5 +653,5 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb)
        WARN_ONCE(true, "ipvlan_handle_frame() called for mode = [%hx]\n",
                          port->mode);
        kfree_skb(skb);
-       return NET_RX_DROP;
+       return RX_HANDLER_CONSUMED;
 }
index 86f6c6292c2726c6991f305bc8794a5af2c648af..06c8bfeaccd6c11cf15a8f05d87ce23c0f1e4405 100644 (file)
@@ -415,6 +415,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
                skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN);
                if (!skb)
                        return RX_HANDLER_CONSUMED;
+               *pskb = skb;
                eth = eth_hdr(skb);
                macvlan_forward_source(skb, port, eth->h_source);
                src = macvlan_hash_lookup(port, eth->h_source);
@@ -456,6 +457,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
                goto out;
        }
 
+       *pskb = skb;
        skb->dev = dev;
        skb->pkt_type = PACKET_HOST;
 
index 97f3acd447985851254d55b546bd625b113641de..06ee6395117f9df71a07d22326bc6c15c1e87f2e 100644 (file)
@@ -244,15 +244,6 @@ static void free_param_target(struct netconsole_target *nt)
  *                             <target>/...
  */
 
-struct netconsole_target_attr {
-       struct configfs_attribute       attr;
-       ssize_t                         (*show)(struct netconsole_target *nt,
-                                               char *buf);
-       ssize_t                         (*store)(struct netconsole_target *nt,
-                                                const char *buf,
-                                                size_t count);
-};
-
 static struct netconsole_target *to_target(struct config_item *item)
 {
        return item ?
@@ -264,58 +255,62 @@ static struct netconsole_target *to_target(struct config_item *item)
  * Attribute operations for netconsole_target.
  */
 
-static ssize_t show_enabled(struct netconsole_target *nt, char *buf)
+static ssize_t enabled_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled);
+       return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled);
 }
 
-static ssize_t show_extended(struct netconsole_target *nt, char *buf)
+static ssize_t extended_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", nt->extended);
+       return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended);
 }
 
-static ssize_t show_dev_name(struct netconsole_target *nt, char *buf)
+static ssize_t dev_name_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%s\n", nt->np.dev_name);
+       return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name);
 }
 
-static ssize_t show_local_port(struct netconsole_target *nt, char *buf)
+static ssize_t local_port_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.local_port);
+       return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port);
 }
 
-static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
+static ssize_t remote_port_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.remote_port);
+       return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port);
 }
 
-static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
+static ssize_t local_ip_show(struct config_item *item, char *buf)
 {
+       struct netconsole_target *nt = to_target(item);
+
        if (nt->np.ipv6)
                return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
        else
                return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
 }
 
-static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
+static ssize_t remote_ip_show(struct config_item *item, char *buf)
 {
+       struct netconsole_target *nt = to_target(item);
+
        if (nt->np.ipv6)
                return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
        else
                return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
 }
 
-static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
+static ssize_t local_mac_show(struct config_item *item, char *buf)
 {
-       struct net_device *dev = nt->np.dev;
+       struct net_device *dev = to_target(item)->np.dev;
        static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
        return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
 }
 
-static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
+static ssize_t remote_mac_show(struct config_item *item, char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
+       return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac);
 }
 
 /*
@@ -325,23 +320,26 @@ static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
  * would enable him to dynamically add new netpoll targets for new
  * network interfaces as and when they come up).
  */
-static ssize_t store_enabled(struct netconsole_target *nt,
-                            const char *buf,
-                            size_t count)
+static ssize_t enabled_store(struct config_item *item,
+               const char *buf, size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
        unsigned long flags;
        int enabled;
        int err;
 
+       mutex_lock(&dynamic_netconsole_mutex);
        err = kstrtoint(buf, 10, &enabled);
        if (err < 0)
-               return err;
+               goto out_unlock;
+
+       err = -EINVAL;
        if (enabled < 0 || enabled > 1)
-               return -EINVAL;
+               goto out_unlock;
        if ((bool)enabled == nt->enabled) {
                pr_info("network logging has already %s\n",
                        nt->enabled ? "started" : "stopped");
-               return -EINVAL;
+               goto out_unlock;
        }
 
        if (enabled) {  /* true */
@@ -358,7 +356,7 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 
                err = netpoll_setup(&nt->np);
                if (err)
-                       return err;
+                       goto out_unlock;
 
                pr_info("netconsole: network logging started\n");
        } else {        /* false */
@@ -374,42 +372,56 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 
        nt->enabled = enabled;
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return err;
 }
 
-static ssize_t store_extended(struct netconsole_target *nt,
-                             const char *buf,
-                             size_t count)
+static ssize_t extended_store(struct config_item *item, const char *buf,
+               size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
        int extended;
        int err;
 
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_unlock;
        }
 
        err = kstrtoint(buf, 10, &extended);
        if (err < 0)
-               return err;
-       if (extended < 0 || extended > 1)
-               return -EINVAL;
+               goto out_unlock;
+       if (extended < 0 || extended > 1) {
+               err = -EINVAL;
+               goto out_unlock;
+       }
 
        nt->extended = extended;
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return err;
 }
 
-static ssize_t store_dev_name(struct netconsole_target *nt,
-                             const char *buf,
-                             size_t count)
+static ssize_t dev_name_store(struct config_item *item, const char *buf,
+               size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
        size_t len;
 
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
+               mutex_unlock(&dynamic_netconsole_mutex);
                return -EINVAL;
        }
 
@@ -420,53 +432,66 @@ static ssize_t store_dev_name(struct netconsole_target *nt,
        if (nt->np.dev_name[len - 1] == '\n')
                nt->np.dev_name[len - 1] = '\0';
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
 }
 
-static ssize_t store_local_port(struct netconsole_target *nt,
-                               const char *buf,
-                               size_t count)
+static ssize_t local_port_store(struct config_item *item, const char *buf,
+               size_t count)
 {
-       int rv;
+       struct netconsole_target *nt = to_target(item);
+       int rv = -EINVAL;
 
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               goto out_unlock;
        }
 
        rv = kstrtou16(buf, 10, &nt->np.local_port);
        if (rv < 0)
-               return rv;
+               goto out_unlock;
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return rv;
 }
 
-static ssize_t store_remote_port(struct netconsole_target *nt,
-                                const char *buf,
-                                size_t count)
+static ssize_t remote_port_store(struct config_item *item,
+               const char *buf, size_t count)
 {
-       int rv;
+       struct netconsole_target *nt = to_target(item);
+       int rv = -EINVAL;
 
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               goto out_unlock;
        }
 
        rv = kstrtou16(buf, 10, &nt->np.remote_port);
        if (rv < 0)
-               return rv;
+               goto out_unlock;
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return rv;
 }
 
-static ssize_t store_local_ip(struct netconsole_target *nt,
-                             const char *buf,
-                             size_t count)
+static ssize_t local_ip_store(struct config_item *item, const char *buf,
+               size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
+
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               goto out_unlock;
        }
 
        if (strnchr(buf, count, ':')) {
@@ -474,29 +499,35 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
                if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
                        if (*end && *end != '\n') {
                                pr_err("invalid IPv6 address at: <%c>\n", *end);
-                               return -EINVAL;
+                               goto out_unlock;
                        }
                        nt->np.ipv6 = true;
                } else
-                       return -EINVAL;
+                       goto out_unlock;
        } else {
                if (!nt->np.ipv6) {
                        nt->np.local_ip.ip = in_aton(buf);
                } else
-                       return -EINVAL;
+                       goto out_unlock;
        }
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return -EINVAL;
 }
 
-static ssize_t store_remote_ip(struct netconsole_target *nt,
-                              const char *buf,
-                              size_t count)
+static ssize_t remote_ip_store(struct config_item *item, const char *buf,
+              size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
+
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               goto out_unlock;
        }
 
        if (strnchr(buf, count, ':')) {
@@ -504,74 +535,71 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
                if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
                        if (*end && *end != '\n') {
                                pr_err("invalid IPv6 address at: <%c>\n", *end);
-                               return -EINVAL;
+                               goto out_unlock;
                        }
                        nt->np.ipv6 = true;
                } else
-                       return -EINVAL;
+                       goto out_unlock;
        } else {
                if (!nt->np.ipv6) {
                        nt->np.remote_ip.ip = in_aton(buf);
                } else
-                       return -EINVAL;
+                       goto out_unlock;
        }
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return -EINVAL;
 }
 
-static ssize_t store_remote_mac(struct netconsole_target *nt,
-                               const char *buf,
-                               size_t count)
+static ssize_t remote_mac_store(struct config_item *item, const char *buf,
+               size_t count)
 {
+       struct netconsole_target *nt = to_target(item);
        u8 remote_mac[ETH_ALEN];
 
+       mutex_lock(&dynamic_netconsole_mutex);
        if (nt->enabled) {
                pr_err("target (%s) is enabled, disable to update parameters\n",
                       config_item_name(&nt->item));
-               return -EINVAL;
+               goto out_unlock;
        }
 
        if (!mac_pton(buf, remote_mac))
-               return -EINVAL;
+               goto out_unlock;
        if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
-               return -EINVAL;
+               goto out_unlock;
        memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
 
+       mutex_unlock(&dynamic_netconsole_mutex);
        return strnlen(buf, count);
+out_unlock:
+       mutex_unlock(&dynamic_netconsole_mutex);
+       return -EINVAL;
 }
 
-/*
- * Attribute definitions for netconsole_target.
- */
-
-#define NETCONSOLE_TARGET_ATTR_RO(_name)                               \
-static struct netconsole_target_attr netconsole_target_##_name =       \
-       __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL)
-
-#define NETCONSOLE_TARGET_ATTR_RW(_name)                               \
-static struct netconsole_target_attr netconsole_target_##_name =       \
-       __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name)
-
-NETCONSOLE_TARGET_ATTR_RW(enabled);
-NETCONSOLE_TARGET_ATTR_RW(extended);
-NETCONSOLE_TARGET_ATTR_RW(dev_name);
-NETCONSOLE_TARGET_ATTR_RW(local_port);
-NETCONSOLE_TARGET_ATTR_RW(remote_port);
-NETCONSOLE_TARGET_ATTR_RW(local_ip);
-NETCONSOLE_TARGET_ATTR_RW(remote_ip);
-NETCONSOLE_TARGET_ATTR_RO(local_mac);
-NETCONSOLE_TARGET_ATTR_RW(remote_mac);
+CONFIGFS_ATTR(, enabled);
+CONFIGFS_ATTR(, extended);
+CONFIGFS_ATTR(, dev_name);
+CONFIGFS_ATTR(, local_port);
+CONFIGFS_ATTR(, remote_port);
+CONFIGFS_ATTR(, local_ip);
+CONFIGFS_ATTR(, remote_ip);
+CONFIGFS_ATTR_RO(, local_mac);
+CONFIGFS_ATTR(, remote_mac);
 
 static struct configfs_attribute *netconsole_target_attrs[] = {
-       &netconsole_target_enabled.attr,
-       &netconsole_target_extended.attr,
-       &netconsole_target_dev_name.attr,
-       &netconsole_target_local_port.attr,
-       &netconsole_target_remote_port.attr,
-       &netconsole_target_local_ip.attr,
-       &netconsole_target_remote_ip.attr,
-       &netconsole_target_local_mac.attr,
-       &netconsole_target_remote_mac.attr,
+       &attr_enabled,
+       &attr_extended,
+       &attr_dev_name,
+       &attr_local_port,
+       &attr_remote_port,
+       &attr_local_ip,
+       &attr_remote_ip,
+       &attr_local_mac,
+       &attr_remote_mac,
        NULL,
 };
 
@@ -584,43 +612,8 @@ static void netconsole_target_release(struct config_item *item)
        kfree(to_target(item));
 }
 
-static ssize_t netconsole_target_attr_show(struct config_item *item,
-                                          struct configfs_attribute *attr,
-                                          char *buf)
-{
-       ssize_t ret = -EINVAL;
-       struct netconsole_target *nt = to_target(item);
-       struct netconsole_target_attr *na =
-               container_of(attr, struct netconsole_target_attr, attr);
-
-       if (na->show)
-               ret = na->show(nt, buf);
-
-       return ret;
-}
-
-static ssize_t netconsole_target_attr_store(struct config_item *item,
-                                           struct configfs_attribute *attr,
-                                           const char *buf,
-                                           size_t count)
-{
-       ssize_t ret = -EINVAL;
-       struct netconsole_target *nt = to_target(item);
-       struct netconsole_target_attr *na =
-               container_of(attr, struct netconsole_target_attr, attr);
-
-       mutex_lock(&dynamic_netconsole_mutex);
-       if (na->store)
-               ret = na->store(nt, buf, count);
-       mutex_unlock(&dynamic_netconsole_mutex);
-
-       return ret;
-}
-
 static struct configfs_item_operations netconsole_target_item_ops = {
        .release                = netconsole_target_release,
-       .show_attribute         = netconsole_target_attr_show,
-       .store_attribute        = netconsole_target_attr_store,
 };
 
 static struct config_item_type netconsole_target_type = {
index fabf11d32d276d9ac6ef6ac50ccd24609a48f90f..2d020a3ec0b5bb0c2ea13dc0f568f123d77af94a 100644 (file)
@@ -308,6 +308,8 @@ static struct phy_driver at803x_driver[] = {
        .flags                  = PHY_HAS_INTERRUPT,
        .config_aneg            = genphy_config_aneg,
        .read_status            = genphy_read_status,
+       .ack_interrupt          = at803x_ack_interrupt,
+       .config_intr            = at803x_config_intr,
        .driver                 = {
                .owner = THIS_MODULE,
        },
@@ -327,6 +329,8 @@ static struct phy_driver at803x_driver[] = {
        .flags                  = PHY_HAS_INTERRUPT,
        .config_aneg            = genphy_config_aneg,
        .read_status            = genphy_read_status,
+       .ack_interrupt          = at803x_ack_interrupt,
+       .config_intr            = at803x_config_intr,
        .driver                 = {
                .owner = THIS_MODULE,
        },
index 5de8d5827536b1c196b4dabe95f3815964dd0296..0240552b50f3228b16fb310afa52a0bdbe8fd4ef 100644 (file)
@@ -1153,6 +1153,21 @@ static struct phy_driver marvell_drivers[] = {
                .suspend = &genphy_suspend,
                .driver = { .owner = THIS_MODULE },
        },
+       {
+               .phy_id = MARVELL_PHY_ID_88E1540,
+               .phy_id_mask = MARVELL_PHY_ID_MASK,
+               .name = "Marvell 88E1540",
+               .features = PHY_GBIT_FEATURES,
+               .flags = PHY_HAS_INTERRUPT,
+               .config_aneg = &m88e1510_config_aneg,
+               .read_status = &marvell_read_status,
+               .ack_interrupt = &marvell_ack_interrupt,
+               .config_intr = &marvell_config_intr,
+               .did_interrupt = &m88e1121_did_interrupt,
+               .resume = &genphy_resume,
+               .suspend = &genphy_suspend,
+               .driver = { .owner = THIS_MODULE },
+       },
        {
                .phy_id = MARVELL_PHY_ID_88E3016,
                .phy_id_mask = MARVELL_PHY_ID_MASK,
@@ -1186,6 +1201,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
        { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
        { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
        { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
+       { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
        { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
        { }
 };
index adb48abafc872a71e801b5505d676f9db02c7466..48ce6ef400fe7fdda6ae78a9a22943b2307c1c8b 100644 (file)
@@ -863,6 +863,9 @@ void phy_state_machine(struct work_struct *work)
                        needs_aneg = true;
                break;
        case PHY_NOLINK:
+               if (phy_interrupt_is_valid(phydev))
+                       break;
+
                err = phy_read_status(phydev);
                if (err)
                        break;
index 76cad712ddb2c7c6bc2794389380e4e0a862d5f5..dd295dbaa074642a7115b65123d06920744c7f88 100644 (file)
@@ -66,6 +66,7 @@
 #define PHY_ID_VSC8244                 0x000fc6c0
 #define PHY_ID_VSC8514                 0x00070670
 #define PHY_ID_VSC8574                 0x000704a0
+#define PHY_ID_VSC8601                 0x00070420
 #define PHY_ID_VSC8662                 0x00070660
 #define PHY_ID_VSC8221                 0x000fc550
 #define PHY_ID_VSC8211                 0x000fc4b0
@@ -133,7 +134,8 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
                        (phydev->drv->phy_id == PHY_ID_VSC8234 ||
                         phydev->drv->phy_id == PHY_ID_VSC8244 ||
                         phydev->drv->phy_id == PHY_ID_VSC8514 ||
-                        phydev->drv->phy_id == PHY_ID_VSC8574) ?
+                        phydev->drv->phy_id == PHY_ID_VSC8574 ||
+                        phydev->drv->phy_id == PHY_ID_VSC8601) ?
                                MII_VSC8244_IMASK_MASK :
                                MII_VSC8221_IMASK_MASK);
        else {
@@ -271,6 +273,18 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_VSC8601,
+       .name           = "Vitesse VSC8601",
+       .phy_id_mask    = 0x000ffff0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &genphy_config_init,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc82xx_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_VSC8662,
        .name           = "Vitesse VSC8662",
index c78d3cb1b4648f771a2b5835e9424cd08c74d182..3da70bf9936a846c5939c389c2d91af1c674af58 100644 (file)
@@ -695,6 +695,11 @@ static const struct usb_device_id  products[] = {
        USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
        .driver_info = (kernel_ulong_t) &wwan_info,
+}, {
+       /* Dell DW5580 modules */
+       USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = (kernel_ulong_t)&wwan_info,
 }, {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
                        USB_CDC_PROTO_NONE),
index 46f4caddccbed84a56b12aad93a683618401fbdb..899ea42881970bb7e579d091696ef9ca1f9aa896 100644 (file)
@@ -2157,12 +2157,13 @@ vmxnet3_set_mc(struct net_device *netdev)
                if (!netdev_mc_empty(netdev)) {
                        new_table = vmxnet3_copy_mc(netdev);
                        if (new_table) {
-                               rxConf->mfTableLen = cpu_to_le16(
-                                       netdev_mc_count(netdev) * ETH_ALEN);
+                               size_t sz = netdev_mc_count(netdev) * ETH_ALEN;
+
+                               rxConf->mfTableLen = cpu_to_le16(sz);
                                new_table_pa = dma_map_single(
                                                        &adapter->pdev->dev,
                                                        new_table,
-                                                       rxConf->mfTableLen,
+                                                       sz,
                                                        PCI_DMA_TODEVICE);
                        }
 
index 3f859a55c035d6ab3b53530c4345083424566404..4c58c83dc2253a43b7c6150866d67bcd0c02e250 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.4.3.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.4.4.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01040300
+#define VMXNET3_DRIVER_VERSION_NUM      0x01040400
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index 8282db2ef99ea02077ef5609b85acfe0a8aae823..b0045a505dc88c9ef56dcc1094a198bd011d24a7 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2015, Intel Corporation.
  */
 #include <linux/platform_device.h>
+#include <linux/memory_hotplug.h>
 #include <linux/libnvdimm.h>
 #include <linux/module.h>
 
@@ -25,6 +26,18 @@ static int e820_pmem_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+static int e820_range_to_nid(resource_size_t addr)
+{
+       return memory_add_physaddr_to_nid(addr);
+}
+#else
+static int e820_range_to_nid(resource_size_t addr)
+{
+       return NUMA_NO_NODE;
+}
+#endif
+
 static int e820_pmem_probe(struct platform_device *pdev)
 {
        static struct nvdimm_bus_descriptor nd_desc;
@@ -48,7 +61,7 @@ static int e820_pmem_probe(struct platform_device *pdev)
                memset(&ndr_desc, 0, sizeof(ndr_desc));
                ndr_desc.res = p;
                ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
-               ndr_desc.numa_node = NUMA_NO_NODE;
+               ndr_desc.numa_node = e820_range_to_nid(p->start);
                set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
                if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
                        goto err;
index 012e0649f1ac48374de47a690a2d0ac1d1865cac..8ee79893d2f5f6f5165558baa22f236738b99c45 100644 (file)
@@ -105,22 +105,11 @@ static long pmem_direct_access(struct block_device *bdev, sector_t sector,
 {
        struct pmem_device *pmem = bdev->bd_disk->private_data;
        resource_size_t offset = sector * 512 + pmem->data_offset;
-       resource_size_t size;
-
-       if (pmem->data_offset) {
-               /*
-                * Limit the direct_access() size to what is covered by
-                * the memmap
-                */
-               size = (pmem->size - offset) & ~ND_PFN_MASK;
-       } else
-               size = pmem->size - offset;
-
-       /* FIXME convert DAX to comprehend that this mapping has a lifetime */
+
        *kaddr = pmem->virt_addr + offset;
        *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
 
-       return size;
+       return pmem->size - offset;
 }
 
 static const struct block_device_operations pmem_fops = {
index e0b7b95813bc98e1fc7f25fd422fad87690ec2e4..9202d1a468d049f30284f39e6c2894e0711b3add 100644 (file)
@@ -93,7 +93,7 @@ struct nvme_nvm_l2ptbl {
        __le16                  cdw14[6];
 };
 
-struct nvme_nvm_bbtbl {
+struct nvme_nvm_getbbtbl {
        __u8                    opcode;
        __u8                    flags;
        __u16                   command_id;
@@ -101,10 +101,23 @@ struct nvme_nvm_bbtbl {
        __u64                   rsvd[2];
        __le64                  prp1;
        __le64                  prp2;
-       __le32                  prp1_len;
-       __le32                  prp2_len;
-       __le32                  lbb;
-       __u32                   rsvd11[3];
+       __le64                  spba;
+       __u32                   rsvd4[4];
+};
+
+struct nvme_nvm_setbbtbl {
+       __u8                    opcode;
+       __u8                    flags;
+       __u16                   command_id;
+       __le32                  nsid;
+       __le64                  rsvd[2];
+       __le64                  prp1;
+       __le64                  prp2;
+       __le64                  spba;
+       __le16                  nlb;
+       __u8                    value;
+       __u8                    rsvd3;
+       __u32                   rsvd4[3];
 };
 
 struct nvme_nvm_erase_blk {
@@ -129,8 +142,8 @@ struct nvme_nvm_command {
                struct nvme_nvm_hb_rw hb_rw;
                struct nvme_nvm_ph_rw ph_rw;
                struct nvme_nvm_l2ptbl l2p;
-               struct nvme_nvm_bbtbl get_bb;
-               struct nvme_nvm_bbtbl set_bb;
+               struct nvme_nvm_getbbtbl get_bb;
+               struct nvme_nvm_setbbtbl set_bb;
                struct nvme_nvm_erase_blk erase;
        };
 };
@@ -142,11 +155,13 @@ struct nvme_nvm_id_group {
        __u8                    num_ch;
        __u8                    num_lun;
        __u8                    num_pln;
+       __u8                    rsvd1;
        __le16                  num_blk;
        __le16                  num_pg;
        __le16                  fpg_sz;
        __le16                  csecs;
        __le16                  sos;
+       __le16                  rsvd2;
        __le32                  trdt;
        __le32                  trdm;
        __le32                  tprt;
@@ -154,8 +169,9 @@ struct nvme_nvm_id_group {
        __le32                  tbet;
        __le32                  tbem;
        __le32                  mpos;
+       __le32                  mccap;
        __le16                  cpar;
-       __u8                    reserved[913];
+       __u8                    reserved[906];
 } __packed;
 
 struct nvme_nvm_addr_format {
@@ -178,15 +194,28 @@ struct nvme_nvm_id {
        __u8                    ver_id;
        __u8                    vmnt;
        __u8                    cgrps;
-       __u8                    res[5];
+       __u8                    res;
        __le32                  cap;
        __le32                  dom;
        struct nvme_nvm_addr_format ppaf;
-       __u8                    ppat;
-       __u8                    resv[223];
+       __u8                    resv[228];
        struct nvme_nvm_id_group groups[4];
 } __packed;
 
+struct nvme_nvm_bb_tbl {
+       __u8    tblid[4];
+       __le16  verid;
+       __le16  revid;
+       __le32  rvsd1;
+       __le32  tblks;
+       __le32  tfact;
+       __le32  tgrown;
+       __le32  tdresv;
+       __le32  thresv;
+       __le32  rsvd2[8];
+       __u8    blk[0];
+};
+
 /*
  * Check we didn't inadvertently grow the command struct
  */
@@ -195,12 +224,14 @@ static inline void _nvme_nvm_check_size(void)
        BUILD_BUG_ON(sizeof(struct nvme_nvm_identity) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_hb_rw) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_ph_rw) != 64);
-       BUILD_BUG_ON(sizeof(struct nvme_nvm_bbtbl) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_nvm_getbbtbl) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_nvm_setbbtbl) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_l2ptbl) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_erase_blk) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_id_group) != 960);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_addr_format) != 128);
        BUILD_BUG_ON(sizeof(struct nvme_nvm_id) != 4096);
+       BUILD_BUG_ON(sizeof(struct nvme_nvm_bb_tbl) != 512);
 }
 
 static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
@@ -234,6 +265,7 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
                dst->tbet = le32_to_cpu(src->tbet);
                dst->tbem = le32_to_cpu(src->tbem);
                dst->mpos = le32_to_cpu(src->mpos);
+               dst->mccap = le32_to_cpu(src->mccap);
 
                dst->cpar = le16_to_cpu(src->cpar);
        }
@@ -244,6 +276,7 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
 static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
 {
        struct nvme_ns *ns = q->queuedata;
+       struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_id *nvme_nvm_id;
        struct nvme_nvm_command c = {};
        int ret;
@@ -256,8 +289,8 @@ static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
        if (!nvme_nvm_id)
                return -ENOMEM;
 
-       ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c, nvme_nvm_id,
-                                               sizeof(struct nvme_nvm_id));
+       ret = nvme_submit_sync_cmd(dev->admin_q, (struct nvme_command *)&c,
+                               nvme_nvm_id, sizeof(struct nvme_nvm_id));
        if (ret) {
                ret = -EIO;
                goto out;
@@ -268,6 +301,8 @@ static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
        nvm_id->cgrps = nvme_nvm_id->cgrps;
        nvm_id->cap = le32_to_cpu(nvme_nvm_id->cap);
        nvm_id->dom = le32_to_cpu(nvme_nvm_id->dom);
+       memcpy(&nvm_id->ppaf, &nvme_nvm_id->ppaf,
+                                       sizeof(struct nvme_nvm_addr_format));
 
        ret = init_grps(nvm_id, nvme_nvm_id);
 out:
@@ -281,7 +316,7 @@ static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
        struct nvme_ns *ns = q->queuedata;
        struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_command c = {};
-       u32 len = queue_max_hw_sectors(q) << 9;
+       u32 len = queue_max_hw_sectors(dev->admin_q) << 9;
        u32 nlb_pr_rq = len / sizeof(u64);
        u64 cmd_slba = slba;
        void *entries;
@@ -299,8 +334,8 @@ static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
                c.l2p.slba = cpu_to_le64(cmd_slba);
                c.l2p.nlb = cpu_to_le32(cmd_nlb);
 
-               ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c,
-                                                               entries, len);
+               ret = nvme_submit_sync_cmd(dev->admin_q,
+                               (struct nvme_command *)&c, entries, len);
                if (ret) {
                        dev_err(dev->dev, "L2P table transfer failed (%d)\n",
                                                                        ret);
@@ -322,43 +357,82 @@ static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
        return ret;
 }
 
-static int nvme_nvm_get_bb_tbl(struct request_queue *q, int lunid,
-                               unsigned int nr_blocks,
-                               nvm_bb_update_fn *update_bbtbl, void *priv)
+static int nvme_nvm_get_bb_tbl(struct request_queue *q, struct ppa_addr ppa,
+                               int nr_blocks, nvm_bb_update_fn *update_bbtbl,
+                               void *priv)
 {
        struct nvme_ns *ns = q->queuedata;
        struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_command c = {};
-       void *bb_bitmap;
-       u16 bb_bitmap_size;
+       struct nvme_nvm_bb_tbl *bb_tbl;
+       int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blocks;
        int ret = 0;
 
        c.get_bb.opcode = nvme_nvm_admin_get_bb_tbl;
        c.get_bb.nsid = cpu_to_le32(ns->ns_id);
-       c.get_bb.lbb = cpu_to_le32(lunid);
-       bb_bitmap_size = ((nr_blocks >> 15) + 1) * PAGE_SIZE;
-       bb_bitmap = kmalloc(bb_bitmap_size, GFP_KERNEL);
-       if (!bb_bitmap)
-               return -ENOMEM;
+       c.get_bb.spba = cpu_to_le64(ppa.ppa);
 
-       bitmap_zero(bb_bitmap, nr_blocks);
+       bb_tbl = kzalloc(tblsz, GFP_KERNEL);
+       if (!bb_tbl)
+               return -ENOMEM;
 
-       ret = nvme_submit_sync_cmd(q, (struct nvme_command *)&c, bb_bitmap,
-                                                               bb_bitmap_size);
+       ret = nvme_submit_sync_cmd(dev->admin_q, (struct nvme_command *)&c,
+                                                               bb_tbl, tblsz);
        if (ret) {
                dev_err(dev->dev, "get bad block table failed (%d)\n", ret);
                ret = -EIO;
                goto out;
        }
 
-       ret = update_bbtbl(lunid, bb_bitmap, nr_blocks, priv);
+       if (bb_tbl->tblid[0] != 'B' || bb_tbl->tblid[1] != 'B' ||
+               bb_tbl->tblid[2] != 'L' || bb_tbl->tblid[3] != 'T') {
+               dev_err(dev->dev, "bbt format mismatch\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (le16_to_cpu(bb_tbl->verid) != 1) {
+               ret = -EINVAL;
+               dev_err(dev->dev, "bbt version not supported\n");
+               goto out;
+       }
+
+       if (le32_to_cpu(bb_tbl->tblks) != nr_blocks) {
+               ret = -EINVAL;
+               dev_err(dev->dev, "bbt unsuspected blocks returned (%u!=%u)",
+                                       le32_to_cpu(bb_tbl->tblks), nr_blocks);
+               goto out;
+       }
+
+       ret = update_bbtbl(ppa, nr_blocks, bb_tbl->blk, priv);
        if (ret) {
                ret = -EINTR;
                goto out;
        }
 
 out:
-       kfree(bb_bitmap);
+       kfree(bb_tbl);
+       return ret;
+}
+
+static int nvme_nvm_set_bb_tbl(struct request_queue *q, struct nvm_rq *rqd,
+                                                               int type)
+{
+       struct nvme_ns *ns = q->queuedata;
+       struct nvme_dev *dev = ns->dev;
+       struct nvme_nvm_command c = {};
+       int ret = 0;
+
+       c.set_bb.opcode = nvme_nvm_admin_set_bb_tbl;
+       c.set_bb.nsid = cpu_to_le32(ns->ns_id);
+       c.set_bb.spba = cpu_to_le64(rqd->ppa_addr.ppa);
+       c.set_bb.nlb = cpu_to_le16(rqd->nr_pages - 1);
+       c.set_bb.value = type;
+
+       ret = nvme_submit_sync_cmd(dev->admin_q, (struct nvme_command *)&c,
+                                                               NULL, 0);
+       if (ret)
+               dev_err(dev->dev, "set bad block table failed (%d)\n", ret);
        return ret;
 }
 
@@ -474,6 +548,7 @@ static struct nvm_dev_ops nvme_nvm_dev_ops = {
        .get_l2p_tbl            = nvme_nvm_get_l2p_tbl,
 
        .get_bb_tbl             = nvme_nvm_get_bb_tbl,
+       .set_bb_tbl             = nvme_nvm_set_bb_tbl,
 
        .submit_io              = nvme_nvm_submit_io,
        .erase_block            = nvme_nvm_erase_block,
index 3dfc28875cc31338be0c33ff040185d03302a3b7..f3b53af789efccbddfedc0b37319dcaa1c264bfd 100644 (file)
@@ -896,19 +896,28 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
                        goto retry_cmd;
                }
                if (blk_integrity_rq(req)) {
-                       if (blk_rq_count_integrity_sg(req->q, req->bio) != 1)
+                       if (blk_rq_count_integrity_sg(req->q, req->bio) != 1) {
+                               dma_unmap_sg(dev->dev, iod->sg, iod->nents,
+                                               dma_dir);
                                goto error_cmd;
+                       }
 
                        sg_init_table(iod->meta_sg, 1);
                        if (blk_rq_map_integrity_sg(
-                                       req->q, req->bio, iod->meta_sg) != 1)
+                                       req->q, req->bio, iod->meta_sg) != 1) {
+                               dma_unmap_sg(dev->dev, iod->sg, iod->nents,
+                                               dma_dir);
                                goto error_cmd;
+                       }
 
                        if (rq_data_dir(req))
                                nvme_dif_remap(req, nvme_dif_prep);
 
-                       if (!dma_map_sg(nvmeq->q_dmadev, iod->meta_sg, 1, dma_dir))
+                       if (!dma_map_sg(nvmeq->q_dmadev, iod->meta_sg, 1, dma_dir)) {
+                               dma_unmap_sg(dev->dev, iod->sg, iod->nents,
+                                               dma_dir);
                                goto error_cmd;
+                       }
                }
        }
 
@@ -968,7 +977,8 @@ static void __nvme_process_cq(struct nvme_queue *nvmeq, unsigned int *tag)
        if (head == nvmeq->cq_head && phase == nvmeq->cq_phase)
                return;
 
-       writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
+       if (likely(nvmeq->cq_vector >= 0))
+               writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
        nvmeq->cq_head = head;
        nvmeq->cq_phase = phase;
 
@@ -1725,11 +1735,15 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
 {
        int result;
        u32 aqa;
-       u64 cap = readq(&dev->bar->cap);
+       u64 cap = lo_hi_readq(&dev->bar->cap);
        struct nvme_queue *nvmeq;
-       unsigned page_shift = PAGE_SHIFT;
+       /*
+        * default to a 4K page size, with the intention to update this
+        * path in the future to accomodate architectures with differing
+        * kernel and IO page sizes.
+        */
+       unsigned page_shift = 12;
        unsigned dev_page_min = NVME_CAP_MPSMIN(cap) + 12;
-       unsigned dev_page_max = NVME_CAP_MPSMAX(cap) + 12;
 
        if (page_shift < dev_page_min) {
                dev_err(dev->dev,
@@ -1738,13 +1752,6 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
                                1 << page_shift);
                return -ENODEV;
        }
-       if (page_shift > dev_page_max) {
-               dev_info(dev->dev,
-                               "Device maximum page size (%u) smaller than "
-                               "host (%u); enabling work-around\n",
-                               1 << dev_page_max, 1 << page_shift);
-               page_shift = dev_page_max;
-       }
 
        dev->subsystem = readl(&dev->bar->vs) >= NVME_VS(1, 1) ?
                                                NVME_CAP_NSSRC(cap) : 0;
@@ -1774,8 +1781,8 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
        dev->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
 
        writel(aqa, &dev->bar->aqa);
-       writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
-       writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
+       lo_hi_writeq(nvmeq->sq_dma_addr, &dev->bar->asq);
+       lo_hi_writeq(nvmeq->cq_dma_addr, &dev->bar->acq);
 
        result = nvme_enable_ctrl(dev, cap);
        if (result)
@@ -2268,7 +2275,7 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
        if (dev->max_hw_sectors) {
                blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
                blk_queue_max_segments(ns->queue,
-                       ((dev->max_hw_sectors << 9) / dev->page_size) + 1);
+                       (dev->max_hw_sectors / (dev->page_size >> 9)) + 1);
        }
        if (dev->stripe_size)
                blk_queue_chunk_sectors(ns->queue, dev->stripe_size >> 9);
@@ -2606,7 +2613,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
        struct pci_dev *pdev = to_pci_dev(dev->dev);
        int res;
        struct nvme_id_ctrl *ctrl;
-       int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
+       int shift = NVME_CAP_MPSMIN(lo_hi_readq(&dev->bar->cap)) + 12;
 
        res = nvme_identify_ctrl(dev, &ctrl);
        if (res) {
@@ -2622,6 +2629,8 @@ static int nvme_dev_add(struct nvme_dev *dev)
        memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
        if (ctrl->mdts)
                dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
+       else
+               dev->max_hw_sectors = UINT_MAX;
        if ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
                        (pdev->device == 0x0953) && ctrl->vs[3]) {
                unsigned int max_hw_sectors;
@@ -2695,7 +2704,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
                        goto unmap;
        }
 
-       cap = readq(&dev->bar->cap);
+       cap = lo_hi_readq(&dev->bar->cap);
        dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
        dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
        dev->dbs = ((void __iomem *)dev->bar) + 4096;
@@ -2758,7 +2767,7 @@ static void nvme_wait_dq(struct nvme_delq_ctx *dq, struct nvme_dev *dev)
                         * queues than admin tags.
                         */
                        set_current_state(TASK_RUNNING);
-                       nvme_disable_ctrl(dev, readq(&dev->bar->cap));
+                       nvme_disable_ctrl(dev, lo_hi_readq(&dev->bar->cap));
                        nvme_clear_queue(dev->queues[0]);
                        flush_kthread_worker(dq->worker);
                        nvme_disable_queue(dev, 0);
@@ -2785,6 +2794,10 @@ static void nvme_del_queue_end(struct nvme_queue *nvmeq)
 {
        struct nvme_delq_ctx *dq = nvmeq->cmdinfo.ctx;
        nvme_put_dq(dq);
+
+       spin_lock_irq(&nvmeq->q_lock);
+       nvme_process_cq(nvmeq);
+       spin_unlock_irq(&nvmeq->q_lock);
 }
 
 static int adapter_async_del_queue(struct nvme_queue *nvmeq, u8 opcode,
@@ -3401,6 +3414,7 @@ static const struct pci_error_handlers nvme_err_handler = {
 
 static const struct pci_device_id nvme_id_table[] = {
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, nvme_id_table);
index ff27177f49edbdd3105b319c7deee29ed48da869..b1449f71601cb257f1057b77c217a943da92cab8 100644 (file)
@@ -143,26 +143,6 @@ void of_pci_check_probe_only(void)
 }
 EXPORT_SYMBOL_GPL(of_pci_check_probe_only);
 
-/**
- * of_pci_dma_configure - Setup DMA configuration
- * @dev: ptr to pci_dev struct of the PCI device
- *
- * Function to update PCI devices's DMA configuration using the same
- * info from the OF node of host bridge's parent (if any).
- */
-void of_pci_dma_configure(struct pci_dev *pci_dev)
-{
-       struct device *dev = &pci_dev->dev;
-       struct device *bridge = pci_get_host_bridge_device(pci_dev);
-
-       if (!bridge->parent)
-               return;
-
-       of_dma_configure(dev, bridge->parent->of_node);
-       pci_put_host_bridge_device(bridge);
-}
-EXPORT_SYMBOL_GPL(of_pci_dma_configure);
-
 #if defined(CONFIG_OF_ADDRESS)
 /**
  * of_pci_get_host_bridge_resources - Parse PCI host bridge resources from DT
index 540f077c37eae7b59b983c31fa6ddce51d8bda6e..02a7452bdf235cf52731b3a822066c27d33e8a76 100644 (file)
@@ -440,7 +440,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
                                         ret, pp->io);
                                continue;
                        }
-                       pp->io_base = pp->io->start;
                        break;
                case IORESOURCE_MEM:
                        pp->mem = win->res;
index 35457ecd8e70f4d6f856573f45f8bbc2991d1f6d..163671a4f798dfc18bb24f3490ad7138753efac1 100644 (file)
@@ -111,7 +111,7 @@ static struct pcie_host_ops hisi_pcie_host_ops = {
        .link_up = hisi_pcie_link_up,
 };
 
-static int __init hisi_add_pcie_port(struct pcie_port *pp,
+static int hisi_add_pcie_port(struct pcie_port *pp,
                                     struct platform_device *pdev)
 {
        int ret;
@@ -139,7 +139,7 @@ static int __init hisi_add_pcie_port(struct pcie_port *pp,
        return 0;
 }
 
-static int __init hisi_pcie_probe(struct platform_device *pdev)
+static int hisi_pcie_probe(struct platform_device *pdev)
 {
        struct hisi_pcie *hisi_pcie;
        struct pcie_port *pp;
index 92618686604cb9d314aa1e6bf833363cfbaaa1b5..eead54cd01b2bfad6a5514f53067429e616db6b7 100644 (file)
@@ -216,7 +216,10 @@ static ssize_t numa_node_store(struct device *dev,
        if (ret)
                return ret;
 
-       if (node >= MAX_NUMNODES || !node_online(node))
+       if ((node < 0 && node != NUMA_NO_NODE) || node >= MAX_NUMNODES)
+               return -EINVAL;
+
+       if (node != NUMA_NO_NODE && !node_online(node))
                return -EINVAL;
 
        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
index fd2f03fa53f33a34977fc8713fd8cf6759cad2d5..d390fc1475eccf9f77491b5b401a823067b2995b 100644 (file)
@@ -337,6 +337,4 @@ static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
 }
 #endif
 
-struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
-
 #endif /* DRIVERS_PCI_H */
index f53b8e85f137902f6e8b0667ae9f0539c06537a1..edb1984201e9702162321c50f33f76ba362bac5a 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/of_device.h>
 #include <linux/of_pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/slab.h>
@@ -13,6 +14,7 @@
 #include <linux/cpumask.h>
 #include <linux/pci-aspm.h>
 #include <linux/aer.h>
+#include <linux/acpi.h>
 #include <asm-generic/pci-bridge.h>
 #include "pci.h"
 
@@ -1672,6 +1674,34 @@ static void pci_set_msi_domain(struct pci_dev *dev)
        dev_set_msi_domain(&dev->dev, d);
 }
 
+/**
+ * pci_dma_configure - Setup DMA configuration
+ * @dev: ptr to pci_dev struct of the PCI device
+ *
+ * Function to update PCI devices's DMA configuration using the same
+ * info from the OF node or ACPI node of host bridge's parent (if any).
+ */
+static void pci_dma_configure(struct pci_dev *dev)
+{
+       struct device *bridge = pci_get_host_bridge_device(dev);
+
+       if (IS_ENABLED(CONFIG_OF) &&
+               bridge->parent && bridge->parent->of_node) {
+                       of_dma_configure(&dev->dev, bridge->parent->of_node);
+       } else if (has_acpi_companion(bridge)) {
+               struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
+               enum dev_dma_attr attr = acpi_get_dma_attr(adev);
+
+               if (attr == DEV_DMA_NOT_SUPPORTED)
+                       dev_warn(&dev->dev, "DMA not supported.\n");
+               else
+                       arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
+                                          attr == DEV_DMA_COHERENT);
+       }
+
+       pci_put_host_bridge_device(bridge);
+}
+
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
        int ret;
@@ -1685,7 +1715,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->dev.coherent_dma_mask = 0xffffffffull;
-       of_pci_dma_configure(dev);
+       pci_dma_configure(dev);
 
        pci_set_dma_max_seg_size(dev, 65536);
        pci_set_dma_seg_boundary(dev, 0xffffffff);
index 3271cd1abe7c0e6c5d2e813171aa5df494f9d977..d03df4a60d057854884eddaeb9f8b2b343bee2d5 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig CHROME_PLATFORMS
        bool "Platform support for Chrome hardware"
+       depends on X86 || ARM || ARM64 || COMPILE_TEST
        ---help---
          Say Y here to get to see options for platform support for
          various Chromebooks and Chromeboxes. This option alone does
@@ -39,7 +40,7 @@ config CHROMEOS_PSTORE
 
 config CROS_EC_CHARDEV
         tristate "Chrome OS Embedded Controller userspace device interface"
-        depends on CROS_EC_PROTO
+        depends on MFD_CROS_EC
         ---help---
           This driver adds support to talk with the ChromeOS EC from userspace.
 
@@ -48,7 +49,7 @@ config CROS_EC_CHARDEV
 
 config CROS_EC_LPC
         tristate "ChromeOS Embedded Controller (LPC)"
-        depends on MFD_CROS_EC && CROS_EC_PROTO && (X86 || COMPILE_TEST)
+        depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
         help
           If you say Y here, you get support for talking to the ChromeOS EC
           over an LPC bus. This uses a simple byte-level protocol with a
index 4a11b010f5d8859e37daad2c1c0d1b381cc5d3a4..bc498bda8211060b145406dea87b36f9e2b931ae 100644 (file)
@@ -1,7 +1,8 @@
 
 obj-$(CONFIG_CHROMEOS_LAPTOP)  += chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)  += chromeos_pstore.o
-cros_ec_devs-objs               := cros_ec_dev.o cros_ec_sysfs.o cros_ec_lightbar.o
+cros_ec_devs-objs              := cros_ec_dev.o cros_ec_sysfs.o \
+                                  cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)   += cros_ec_devs.o
 obj-$(CONFIG_CROS_EC_LPC)       += cros_ec_lpc.o
 obj-$(CONFIG_CROS_EC_PROTO)    += cros_ec_proto.o
index 02072749fff3718ddc119aab5b24b4ecafbe53ff..2b441e9ae593518dd7ac0ade3168e8928436f042 100644 (file)
@@ -47,8 +47,8 @@ static const char *i2c_adapter_names[] = {
        "SMBus I801 adapter",
        "i915 gmbus vga",
        "i915 gmbus panel",
-       "i2c-designware-pci",
-       "i2c-designware-pci",
+       "Synopsys DesignWare I2C adapter",
+       "Synopsys DesignWare I2C adapter",
 };
 
 /* Keep this enum consistent with i2c_adapter_names */
index e8fcdc237029a97908194a52b668ad0c4aa6920c..d45cd254ed1c8f295292074100934130235fca64 100644 (file)
@@ -32,6 +32,7 @@ static int ec_major;
 static const struct attribute_group *cros_ec_groups[] = {
        &cros_ec_attr_group,
        &cros_ec_lightbar_attr_group,
+       &cros_ec_vbc_attr_group,
        NULL,
 };
 
@@ -287,6 +288,12 @@ static int ec_device_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct platform_device_id cros_ec_id[] = {
+       { "cros-ec-ctl", 0 },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_id);
+
 static struct platform_driver cros_ec_dev_driver = {
        .driver = {
                .name = "cros-ec-ctl",
index 144e09df9b846551edb9b2c9df6c7be8f717c697..ff7640575c751dfbc401486eee0f982c3527b1ff 100644 (file)
@@ -252,7 +252,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
 
                ret = sscanf(buf, "%i", &val[i++]);
                if (ret == 0)
-                       return -EINVAL;
+                       goto exit;
 
                if (i == 4) {
                        param = (struct ec_params_lightbar *)msg->data;
@@ -268,17 +268,15 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
                        if ((j++ % 4) == 0) {
                                ret = lb_throttle();
                                if (ret)
-                                       return ret;
+                                       goto exit;
                        }
 
                        ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
                        if (ret < 0)
                                goto exit;
 
-                       if (msg->result != EC_RES_SUCCESS) {
-                               ret = -EINVAL;
+                       if (msg->result != EC_RES_SUCCESS)
                                goto exit;
-                       }
 
                        i = 0;
                        ok = 1;
@@ -352,10 +350,6 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
        struct cros_ec_dev *ec = container_of(dev,
                                              struct cros_ec_dev, class_dev);
 
-       msg = alloc_lightbar_cmd_msg(ec);
-       if (!msg)
-               return -ENOMEM;
-
        for (len = 0; len < count; len++)
                if (!isalnum(buf[len]))
                        break;
@@ -370,21 +364,30 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
                        return ret;
        }
 
+       msg = alloc_lightbar_cmd_msg(ec);
+       if (!msg)
+               return -ENOMEM;
+
        param = (struct ec_params_lightbar *)msg->data;
        param->cmd = LIGHTBAR_CMD_SEQ;
        param->seq.num = num;
        ret = lb_throttle();
        if (ret)
-               return ret;
+               goto exit;
 
        ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
        if (ret < 0)
-               return ret;
+               goto exit;
 
-       if (msg->result != EC_RES_SUCCESS)
-               return -EINVAL;
+       if (msg->result != EC_RES_SUCCESS) {
+               ret = -EINVAL;
+               goto exit;
+       }
 
-       return count;
+       ret = count;
+exit:
+       kfree(msg);
+       return ret;
 }
 
 /* Module initialization */
index bdd77ce45f0512494fa775dba51fc8655be1a8c4..f9a245465fd099f64037711523f7b0903b9b226d 100644 (file)
@@ -166,19 +166,9 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
 
        /* Check result */
        msg->result = inb(EC_LPC_ADDR_HOST_DATA);
-
-       switch (msg->result) {
-       case EC_RES_SUCCESS:
-               break;
-       case EC_RES_IN_PROGRESS:
-               ret = -EAGAIN;
-               dev_dbg(ec->dev, "command 0x%02x in progress\n",
-                       msg->command);
+       ret = cros_ec_check_result(ec, msg);
+       if (ret)
                goto done;
-       default:
-               dev_dbg(ec->dev, "command 0x%02x returned %d\n",
-                       msg->command, msg->result);
-       }
 
        /* Read back args */
        args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
@@ -329,6 +319,13 @@ static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
                },
        },
+       {
+               /* x86-samus, the Chromebook Pixel 2. */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+               },
+       },
        {
                /* x86-peppy, the Acer C720 Chromebook. */
                .matches = {
diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c
new file mode 100644 (file)
index 0000000..564a0d0
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * cros_ec_vbc - Expose the vboot context nvram to userspace
+ *
+ * Copyright (C) 2015 Collabora Ltd.
+ *
+ * based on vendor driver,
+ *
+ * Copyright (C) 2012 The Chromium OS Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/slab.h>
+
+static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
+                                 struct bin_attribute *att, char *buf,
+                                 loff_t pos, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+                                             class_dev);
+       struct cros_ec_device *ecdev = ec->ec_dev;
+       struct ec_params_vbnvcontext *params;
+       struct cros_ec_command *msg;
+       int err;
+       const size_t para_sz = sizeof(params->op);
+       const size_t resp_sz = sizeof(struct ec_response_vbnvcontext);
+       const size_t payload = max(para_sz, resp_sz);
+
+       msg = kmalloc(sizeof(*msg) + payload, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       /* NB: we only kmalloc()ated enough space for the op field */
+       params = (struct ec_params_vbnvcontext *)msg->data;
+       params->op = EC_VBNV_CONTEXT_OP_READ;
+
+       msg->version = EC_VER_VBNV_CONTEXT;
+       msg->command = EC_CMD_VBNV_CONTEXT;
+       msg->outsize = para_sz;
+       msg->insize = resp_sz;
+
+       err = cros_ec_cmd_xfer(ecdev, msg);
+       if (err < 0) {
+               dev_err(dev, "Error sending read request: %d\n", err);
+               kfree(msg);
+               return err;
+       }
+
+       memcpy(buf, msg->data, resp_sz);
+
+       kfree(msg);
+       return resp_sz;
+}
+
+static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
+                                  struct bin_attribute *attr, char *buf,
+                                  loff_t pos, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+                                             class_dev);
+       struct cros_ec_device *ecdev = ec->ec_dev;
+       struct ec_params_vbnvcontext *params;
+       struct cros_ec_command *msg;
+       int err;
+       const size_t para_sz = sizeof(*params);
+       const size_t data_sz = sizeof(params->block);
+
+       /* Only write full values */
+       if (count != data_sz)
+               return -EINVAL;
+
+       msg = kmalloc(sizeof(*msg) + para_sz, GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       params = (struct ec_params_vbnvcontext *)msg->data;
+       params->op = EC_VBNV_CONTEXT_OP_WRITE;
+       memcpy(params->block, buf, data_sz);
+
+       msg->version = EC_VER_VBNV_CONTEXT;
+       msg->command = EC_CMD_VBNV_CONTEXT;
+       msg->outsize = para_sz;
+       msg->insize = 0;
+
+       err = cros_ec_cmd_xfer(ecdev, msg);
+       if (err < 0) {
+               dev_err(dev, "Error sending write request: %d\n", err);
+               kfree(msg);
+               return err;
+       }
+
+       kfree(msg);
+       return data_sz;
+}
+
+static umode_t cros_ec_vbc_is_visible(struct kobject *kobj,
+                                     struct bin_attribute *a, int n)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
+                                             class_dev);
+       struct device_node *np = ec->ec_dev->dev->of_node;
+
+       if (IS_ENABLED(CONFIG_OF) && np) {
+               if (of_property_read_bool(np, "google,has-vbc-nvram"))
+                       return a->attr.mode;
+       }
+
+       return 0;
+}
+
+static BIN_ATTR_RW(vboot_context, 16);
+
+static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
+       &bin_attr_vboot_context,
+       NULL
+};
+
+struct attribute_group cros_ec_vbc_attr_group = {
+       .name = "vbc",
+       .bin_attrs = cros_ec_vbc_bin_attrs,
+       .is_bin_visible = cros_ec_vbc_is_visible,
+};
index 02bbc70c332dd8fb2d241974e5e41f140aa8a8c3..1089eaa02b00b07369b6de923c5b2217d432d26c 100644 (file)
@@ -345,6 +345,7 @@ config IDEAPAD_LAPTOP
        depends on SERIO_I8042
        depends on BACKLIGHT_CLASS_DEVICE
        depends on ACPI_VIDEO || ACPI_VIDEO = n
+       depends on ACPI_WMI || ACPI_WMI = n
        select INPUT_SPARSEKMAP
        help
          This is a driver for Lenovo IdeaPad netbooks contains drivers for
index e3a750224ae224b2265ef73003f2b28088518d99..f96f7b865267925086f464addccd7f1ef2314ac0 100644 (file)
@@ -1682,7 +1682,7 @@ static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
        int rv, err, value;
 
        value = asus_wmi_get_devstate_simple(asus, devid);
-       if (value == -ENODEV)   /* Check device presence */
+       if (value < 0)
                return value;
 
        rv = parse_arg(buf, count, &value);
index fce49f3c6ed688f676aea9be4647cc63d3c56416..a313dfc0245f550ac5322fec17d890662d52e790 100644 (file)
 #define CFG_WIFI_BIT   (18)
 #define CFG_CAMERA_BIT (19)
 
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+static const char ideapad_wmi_fnesc_event[] = "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6";
+#endif
+
 enum {
        VPCCMD_R_VPC1 = 0x10,
        VPCCMD_R_BL_MAX,
@@ -567,6 +571,8 @@ static const struct key_entry ideapad_keymap[] = {
        { KE_KEY, 65, { KEY_PROG4 } },
        { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
        { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
+       { KE_KEY, 128, { KEY_ESC } },
+
        { KE_END, 0 },
 };
 
@@ -825,6 +831,19 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
        }
 }
 
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+static void ideapad_wmi_notify(u32 value, void *context)
+{
+       switch (value) {
+       case 128:
+               ideapad_input_report(context, value);
+               break;
+       default:
+               pr_info("Unknown WMI event %u\n", value);
+       }
+}
+#endif
+
 /*
  * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
  * always results in 0 on these models, causing ideapad_laptop to wrongly
@@ -853,24 +872,31 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                },
        },
        {
-               .ident = "Lenovo Yoga 3 14",
+               .ident = "Lenovo Yoga 2 11 / 13 / Pro",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
                },
        },
        {
-               .ident = "Lenovo Yoga 2 11 / 13 / Pro",
+               .ident = "Lenovo Yoga 3 1170 / 1470",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3"),
                },
        },
        {
                .ident = "Lenovo Yoga 3 Pro 1370",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3 Pro-1370"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"),
+               },
+       },
+       {
+               .ident = "Lenovo Yoga 900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
                },
        },
        {}
@@ -935,8 +961,18 @@ static int ideapad_acpi_add(struct platform_device *pdev)
                ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
        if (ret)
                goto notification_failed;
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+       ret = wmi_install_notify_handler(ideapad_wmi_fnesc_event, ideapad_wmi_notify, priv);
+       if (ret != AE_OK && ret != AE_NOT_EXIST)
+               goto notification_failed_wmi;
+#endif
 
        return 0;
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+notification_failed_wmi:
+       acpi_remove_notify_handler(priv->adev->handle,
+               ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
+#endif
 notification_failed:
        ideapad_backlight_exit(priv);
 backlight_failed:
@@ -955,6 +991,9 @@ static int ideapad_acpi_remove(struct platform_device *pdev)
        struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
        int i;
 
+#if IS_ENABLED(CONFIG_ACPI_WMI)
+       wmi_remove_notify_handler(ideapad_wmi_fnesc_event);
+#endif
        acpi_remove_notify_handler(priv->adev->handle,
                ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
        ideapad_backlight_exit(priv);
index 131dd74641833e69e144f6a22d1d4021d09ee1c9..0bed4733c4f04925831a174b6b58e674ca2fe56c 100644 (file)
@@ -6459,8 +6459,7 @@ static void __init tpacpi_detect_brightness_capabilities(void)
                pr_info("detected a 8-level brightness capable ThinkPad\n");
                break;
        default:
-               pr_err("Unsupported brightness interface, "
-                      "please contact %s\n", TPACPI_MAIL);
+               pr_info("Unsupported brightness interface\n");
                tp_features.bright_unkfw = 1;
                bright_maxlvl = b - 1;
        }
index 548a18916a31ec11f5abf0fae9c3626755422d46..a831d18596a5ef592f88ec5af031f639606c8c0b 100644 (file)
@@ -1080,28 +1080,10 @@ void __init chsc_init_cleanup(void)
        free_page((unsigned long)sei_page);
 }
 
-int chsc_enable_facility(int operation_code)
+int __chsc_enable_facility(struct chsc_sda_area *sda_area, int operation_code)
 {
-       unsigned long flags;
        int ret;
-       struct {
-               struct chsc_header request;
-               u8 reserved1:4;
-               u8 format:4;
-               u8 reserved2;
-               u16 operation_code;
-               u32 reserved3;
-               u32 reserved4;
-               u32 operation_data_area[252];
-               struct chsc_header response;
-               u32 reserved5:4;
-               u32 format2:4;
-               u32 reserved6:24;
-       } __attribute__ ((packed)) *sda_area;
 
-       spin_lock_irqsave(&chsc_page_lock, flags);
-       memset(chsc_page, 0, PAGE_SIZE);
-       sda_area = chsc_page;
        sda_area->request.length = 0x0400;
        sda_area->request.code = 0x0031;
        sda_area->operation_code = operation_code;
@@ -1119,10 +1101,25 @@ int chsc_enable_facility(int operation_code)
        default:
                ret = chsc_error_from_response(sda_area->response.code);
        }
+out:
+       return ret;
+}
+
+int chsc_enable_facility(int operation_code)
+{
+       struct chsc_sda_area *sda_area;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&chsc_page_lock, flags);
+       memset(chsc_page, 0, PAGE_SIZE);
+       sda_area = chsc_page;
+
+       ret = __chsc_enable_facility(sda_area, operation_code);
        if (ret != 0)
                CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
                              operation_code, sda_area->response.code);
-out:
+
        spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
 }
index 76c9b50700b24975842713560b4d4fce2e9ddba6..0de134c3a2044be8956a31fa01c142d581e3a792 100644 (file)
@@ -115,6 +115,20 @@ struct chsc_scpd {
        u8 data[PAGE_SIZE - 20];
 } __attribute__ ((packed));
 
+struct chsc_sda_area {
+       struct chsc_header request;
+       u8 :4;
+       u8 format:4;
+       u8 :8;
+       u16 operation_code;
+       u32 :32;
+       u32 :32;
+       u32 operation_data_area[252];
+       struct chsc_header response;
+       u32 :4;
+       u32 format2:4;
+       u32 :24;
+} __packed __aligned(PAGE_SIZE);
 
 extern int chsc_get_ssd_info(struct subchannel_id schid,
                             struct chsc_ssd_info *ssd);
@@ -122,6 +136,7 @@ extern int chsc_determine_css_characteristics(void);
 extern int chsc_init(void);
 extern void chsc_init_cleanup(void);
 
+int __chsc_enable_facility(struct chsc_sda_area *sda_area, int operation_code);
 extern int chsc_enable_facility(int);
 struct channel_subsystem;
 extern int chsc_secm(struct channel_subsystem *, int);
index b5620e818d6b91307c329cfe67f2de5ac4847ca5..690b8547e828deb81d94a2646459d2babc79dc24 100644 (file)
@@ -925,18 +925,32 @@ void reipl_ccw_dev(struct ccw_dev_id *devid)
 
 int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
 {
+       static struct chsc_sda_area sda_area __initdata;
        struct subchannel_id schid;
        struct schib schib;
 
        schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id;
        if (!schid.one)
                return -ENODEV;
+
+       if (schid.ssid) {
+               /*
+                * Firmware should have already enabled MSS but whoever started
+                * the kernel might have initiated a channel subsystem reset.
+                * Ensure that MSS is enabled.
+                */
+               memset(&sda_area, 0, sizeof(sda_area));
+               if (__chsc_enable_facility(&sda_area, CHSC_SDA_OC_MSS))
+                       return -ENODEV;
+       }
        if (stsch_err(schid, &schib))
                return -ENODEV;
        if (schib.pmcw.st != SUBCHANNEL_TYPE_IO)
                return -ENODEV;
        if (!schib.pmcw.dnv)
                return -ENODEV;
+
+       iplinfo->ssid = schid.ssid;
        iplinfo->devno = schib.pmcw.dev;
        iplinfo->is_qdio = schib.pmcw.qf;
        return 0;
index 2ee3053bdc124319abf79a91f3ba07eb66835524..489e703dc82d85b49d33990bd3d5c2b687d9eb0f 100644 (file)
@@ -702,17 +702,12 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
                css->global_pgid.pgid_high.ext_cssid.version = 0x80;
                css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
        } else {
-#ifdef CONFIG_SMP
                css->global_pgid.pgid_high.cpu_addr = stap();
-#else
-               css->global_pgid.pgid_high.cpu_addr = 0;
-#endif
        }
        get_cpu_id(&cpu_id);
        css->global_pgid.cpu_id = cpu_id.ident;
        css->global_pgid.cpu_model = cpu_id.machine;
        css->global_pgid.tod_high = tod_high;
-
 }
 
 static void
index 57f710b3c8a42862357d65653494f72d89580b32..b8ab18676e69a39d2077fa3b5ff7c192ed3d3fe9 100644 (file)
@@ -3,6 +3,9 @@
 #
 
 ap-objs := ap_bus.o
-obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcixcc.o
-obj-$(CONFIG_ZCRYPT) += zcrypt_cex2a.o zcrypt_cex4.o
+# zcrypt_api depends on ap
+obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o
+# msgtype* depend on zcrypt_api
 obj-$(CONFIG_ZCRYPT) += zcrypt_msgtype6.o zcrypt_msgtype50.o
+# adapter drivers depend on ap, zcrypt_api and msgtype*
+obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o
index 9cb3dfbcaddbc491f537fc431471a16a98f50b69..61f768518a34b0e963cd6b569610045a3f65188b 100644 (file)
@@ -74,6 +74,7 @@ static struct device *ap_root_device = NULL;
 static struct ap_config_info *ap_configuration;
 static DEFINE_SPINLOCK(ap_device_list_lock);
 static LIST_HEAD(ap_device_list);
+static bool initialised;
 
 /*
  * Workqueue timer for bus rescan.
@@ -1384,6 +1385,9 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
 {
        struct device_driver *drv = &ap_drv->driver;
 
+       if (!initialised)
+               return -ENODEV;
+
        drv->bus = &ap_bus_type;
        drv->probe = ap_device_probe;
        drv->remove = ap_device_remove;
@@ -1808,6 +1812,7 @@ int __init ap_module_init(void)
                goto out_pm;
 
        queue_work(system_long_wq, &ap_scan_work);
+       initialised = true;
 
        return 0;
 
@@ -1837,6 +1842,7 @@ void ap_module_exit(void)
 {
        int i;
 
+       initialised = false;
        ap_reset_domain();
        ap_poll_thread_stop();
        del_timer_sync(&ap_config_timer);
index a9603ebbc1f8fdd6ca03eb9b4702d356648157b4..9f8fa42c062c22f59681f2e18026214d39a2b7c0 100644 (file)
@@ -317,11 +317,9 @@ EXPORT_SYMBOL(zcrypt_device_unregister);
 
 void zcrypt_msgtype_register(struct zcrypt_ops *zops)
 {
-       if (zops->owner) {
-               spin_lock_bh(&zcrypt_ops_list_lock);
-               list_add_tail(&zops->list, &zcrypt_ops_list);
-               spin_unlock_bh(&zcrypt_ops_list_lock);
-       }
+       spin_lock_bh(&zcrypt_ops_list_lock);
+       list_add_tail(&zops->list, &zcrypt_ops_list);
+       spin_unlock_bh(&zcrypt_ops_list_lock);
 }
 EXPORT_SYMBOL(zcrypt_msgtype_register);
 
@@ -342,7 +340,7 @@ struct zcrypt_ops *__ops_lookup(unsigned char *name, int variant)
        spin_lock_bh(&zcrypt_ops_list_lock);
        list_for_each_entry(zops, &zcrypt_ops_list, list) {
                if ((zops->variant == variant) &&
-                   (!strncmp(zops->owner->name, name, MODULE_NAME_LEN))) {
+                   (!strncmp(zops->name, name, sizeof(zops->name)))) {
                        found = 1;
                        break;
                }
index 750876891931627641131a59dfd58df2c4e8f8ce..38618f05ad924c340d324500d9d3b887798c7cd8 100644 (file)
@@ -96,6 +96,7 @@ struct zcrypt_ops {
        struct list_head list;          /* zcrypt ops list. */
        struct module *owner;
        int variant;
+       char name[128];
 };
 
 struct zcrypt_device {
index 71ceee9137a88919d8c53ca7148afff0a7211e95..74edf2934e7c9fd652c33d1d14bb47b9e2bf44b8 100644 (file)
@@ -513,6 +513,7 @@ static struct zcrypt_ops zcrypt_msgtype50_ops = {
        .rsa_modexpo = zcrypt_cex2a_modexpo,
        .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt,
        .owner = THIS_MODULE,
+       .name = MSGTYPE50_NAME,
        .variant = MSGTYPE50_VARIANT_DEFAULT,
 };
 
index 74762214193b0326a8ee2cb6d21141f3c414123b..9a2dd472c1cc9870d37e98c5692c1c9c1e0ebac3 100644 (file)
@@ -1119,6 +1119,7 @@ static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
  */
 static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
        .owner = THIS_MODULE,
+       .name = MSGTYPE06_NAME,
        .variant = MSGTYPE06_VARIANT_NORNG,
        .rsa_modexpo = zcrypt_msgtype6_modexpo,
        .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
@@ -1127,6 +1128,7 @@ static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
 
 static struct zcrypt_ops zcrypt_msgtype6_ops = {
        .owner = THIS_MODULE,
+       .name = MSGTYPE06_NAME,
        .variant = MSGTYPE06_VARIANT_DEFAULT,
        .rsa_modexpo = zcrypt_msgtype6_modexpo,
        .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
@@ -1136,6 +1138,7 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = {
 
 static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
        .owner = THIS_MODULE,
+       .name = MSGTYPE06_NAME,
        .variant = MSGTYPE06_VARIANT_EP11,
        .rsa_modexpo = NULL,
        .rsa_modexpo_crt = NULL,
index a209c341889830127fa6ca5e72bde71d141432e7..d4c285688ce98b8222dcc778ee646f6581e48df3 100644 (file)
@@ -325,7 +325,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        tpnt->slave_destroy = NCR_700_slave_destroy;
        tpnt->slave_alloc = NCR_700_slave_alloc;
        tpnt->change_queue_depth = NCR_700_change_queue_depth;
-       tpnt->use_blk_tags = 1;
 
        if(tpnt->name == NULL)
                tpnt->name = "53c700";
@@ -1107,7 +1106,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                        BUG();
                }
                if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) {
-                       struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]);
+                       struct scsi_cmnd *SCp;
+
+                       SCp = scsi_host_find_tag(SDp->host, hostdata->msgin[2]);
                        if(unlikely(SCp == NULL)) {
                                printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n", 
                                       host->host_no, reselection_id, lun, hostdata->msgin[2]);
@@ -1119,7 +1120,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                                "reselection is tag %d, slot %p(%d)\n",
                                hostdata->msgin[2], slot, slot->tag);
                } else {
-                       struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG);
+                       struct scsi_cmnd *SCp;
+
+                       SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
                        if(unlikely(SCp == NULL)) {
                                sdev_printk(KERN_ERR, SDp,
                                        "no saved request for untagged cmd\n");
@@ -1823,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
                       slot->tag, slot);
        } else {
                slot->tag = SCSI_NO_TAG;
-               /* must populate current_cmnd for scsi_find_tag to work */
+               /* must populate current_cmnd for scsi_host_find_tag to work */
                SCp->device->current_cmnd = SCp;
        }
        /* sanity check: some of the commands generated by the mid-layer
index 5c74e4c52fe4448af1df385c29c594e50d15f9b7..867b864f50479033bd5e206de8bec23cd4a0a81a 100644 (file)
@@ -2136,7 +2136,7 @@ static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
  *
  *---------------------------------------------------------------------*/
 
-static void FPT_SccbMgrTableInitAll()
+static void FPT_SccbMgrTableInitAll(void)
 {
        unsigned char thisCard;
 
index d2f480b04a52ed4f882fe3ca9b0b79113ef804a4..5f692ae4074959e019a74eb0c81405cb2869195c 100644 (file)
@@ -534,7 +534,6 @@ config SCSI_ARCMSR
 
 source "drivers/scsi/esas2r/Kconfig"
 source "drivers/scsi/megaraid/Kconfig.megaraid"
-source "drivers/scsi/mpt2sas/Kconfig"
 source "drivers/scsi/mpt3sas/Kconfig"
 source "drivers/scsi/ufs/Kconfig"
 
index 1a8c9b53fafad5900ef775599a7f34abd34978eb..c14bca4a9675c1d1ce29d759354cd8a835bdf98d 100644 (file)
@@ -106,7 +106,6 @@ obj-$(CONFIG_CXLFLASH)              += cxlflash/
 obj-$(CONFIG_MEGARAID_LEGACY)  += megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)  += megaraid/
 obj-$(CONFIG_MEGARAID_SAS)     += megaraid/
-obj-$(CONFIG_SCSI_MPT2SAS)     += mpt2sas/
 obj-$(CONFIG_SCSI_MPT3SAS)     += mpt3sas/
 obj-$(CONFIG_SCSI_UFSHCD)      += ufs/
 obj-$(CONFIG_SCSI_ACARD)       += atp870u.o
index 9b3dd6ef6a0b75794480beedcbaa44965a81bd76..e4c243748a97f97d2fa16b1b2ee6622e83b3905e 100644 (file)
@@ -259,7 +259,7 @@ MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
        " 0=off, 1=on");
 module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(msi, "IRQ handling."
-       " 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
+       " 0=PIC(default), 1=MSI, 2=MSI-X)");
 module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
        " adapter to have it's kernel up and\n"
@@ -570,7 +570,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
 
        status = aac_fib_send(ContainerCommand,
                  cmd_fibcontext,
-                 sizeof (struct aac_get_name),
+                 sizeof(struct aac_get_name_resp),
                  FsaNormal,
                  0, 1,
                  (fib_callback)get_container_name_callback,
@@ -1052,7 +1052,7 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
 
        status = aac_fib_send(ContainerCommand,
                  cmd_fibcontext,
-                 sizeof (struct aac_get_serial),
+                 sizeof(struct aac_get_serial_resp),
                  FsaNormal,
                  0, 1,
                  (fib_callback) get_container_serial_callback,
@@ -2977,11 +2977,16 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                return;
 
        BUG_ON(fibptr == NULL);
-
        dev = fibptr->dev;
 
-       srbreply = (struct aac_srb_reply *) fib_data(fibptr);
+       scsi_dma_unmap(scsicmd);
 
+       /* expose physical device if expose_physicald flag is on */
+       if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
+         && expose_physicals > 0)
+               aac_expose_phy_device(scsicmd);
+
+       srbreply = (struct aac_srb_reply *) fib_data(fibptr);
        scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
 
        if (fibptr->flags & FIB_CONTEXT_FLAG_FASTRESP) {
@@ -2994,147 +2999,157 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
                 */
                scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
                                   - le32_to_cpu(srbreply->data_xfer_length));
-       }
-
-       scsi_dma_unmap(scsicmd);
-
-       /* expose physical device if expose_physicald flag is on */
-       if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
-         && expose_physicals > 0)
-               aac_expose_phy_device(scsicmd);
+               /*
+                * First check the fib status
+                */
 
-       /*
-        * First check the fib status
-        */
+               if (le32_to_cpu(srbreply->status) != ST_OK) {
+                       int len;
 
-       if (le32_to_cpu(srbreply->status) != ST_OK){
-               int len;
-               printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
-               len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
-                           SCSI_SENSE_BUFFERSIZE);
-               scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
-               memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
-       }
+                       printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
+                       len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
+                                   SCSI_SENSE_BUFFERSIZE);
+                       scsicmd->result = DID_ERROR << 16
+                                               | COMMAND_COMPLETE << 8
+                                               | SAM_STAT_CHECK_CONDITION;
+                       memcpy(scsicmd->sense_buffer,
+                                       srbreply->sense_data, len);
+               }
 
-       /*
-        * Next check the srb status
-        */
-       switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
-       case SRB_STATUS_ERROR_RECOVERY:
-       case SRB_STATUS_PENDING:
-       case SRB_STATUS_SUCCESS:
-               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
-               break;
-       case SRB_STATUS_DATA_OVERRUN:
-               switch(scsicmd->cmnd[0]){
-               case  READ_6:
-               case  WRITE_6:
-               case  READ_10:
-               case  WRITE_10:
-               case  READ_12:
-               case  WRITE_12:
-               case  READ_16:
-               case  WRITE_16:
-                       if (le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow) {
-                               printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
-                       } else {
-                               printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
+               /*
+                * Next check the srb status
+                */
+               switch ((le32_to_cpu(srbreply->srb_status))&0x3f) {
+               case SRB_STATUS_ERROR_RECOVERY:
+               case SRB_STATUS_PENDING:
+               case SRB_STATUS_SUCCESS:
+                       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+                       break;
+               case SRB_STATUS_DATA_OVERRUN:
+                       switch (scsicmd->cmnd[0]) {
+                       case  READ_6:
+                       case  WRITE_6:
+                       case  READ_10:
+                       case  WRITE_10:
+                       case  READ_12:
+                       case  WRITE_12:
+                       case  READ_16:
+                       case  WRITE_16:
+                               if (le32_to_cpu(srbreply->data_xfer_length)
+                                                       < scsicmd->underflow)
+                                       printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
+                               else
+                                       printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
+                               scsicmd->result = DID_ERROR << 16
+                                                       | COMMAND_COMPLETE << 8;
+                               break;
+                       case INQUIRY: {
+                               scsicmd->result = DID_OK << 16
+                                                       | COMMAND_COMPLETE << 8;
+                               break;
+                       }
+                       default:
+                               scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+                               break;
                        }
-                       scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
                        break;
-               case INQUIRY: {
-                       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+               case SRB_STATUS_ABORTED:
+                       scsicmd->result = DID_ABORT << 16 | ABORT << 8;
                        break;
-               }
-               default:
-                       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
+               case SRB_STATUS_ABORT_FAILED:
+                       /*
+                        * Not sure about this one - but assuming the
+                        * hba was trying to abort for some reason
+                        */
+                       scsicmd->result = DID_ERROR << 16 | ABORT << 8;
+                       break;
+               case SRB_STATUS_PARITY_ERROR:
+                       scsicmd->result = DID_PARITY << 16
+                                               | MSG_PARITY_ERROR << 8;
+                       break;
+               case SRB_STATUS_NO_DEVICE:
+               case SRB_STATUS_INVALID_PATH_ID:
+               case SRB_STATUS_INVALID_TARGET_ID:
+               case SRB_STATUS_INVALID_LUN:
+               case SRB_STATUS_SELECTION_TIMEOUT:
+                       scsicmd->result = DID_NO_CONNECT << 16
+                                               | COMMAND_COMPLETE << 8;
                        break;
-               }
-               break;
-       case SRB_STATUS_ABORTED:
-               scsicmd->result = DID_ABORT << 16 | ABORT << 8;
-               break;
-       case SRB_STATUS_ABORT_FAILED:
-               // Not sure about this one - but assuming the hba was trying to abort for some reason
-               scsicmd->result = DID_ERROR << 16 | ABORT << 8;
-               break;
-       case SRB_STATUS_PARITY_ERROR:
-               scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
-               break;
-       case SRB_STATUS_NO_DEVICE:
-       case SRB_STATUS_INVALID_PATH_ID:
-       case SRB_STATUS_INVALID_TARGET_ID:
-       case SRB_STATUS_INVALID_LUN:
-       case SRB_STATUS_SELECTION_TIMEOUT:
-               scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
-               break;
 
-       case SRB_STATUS_COMMAND_TIMEOUT:
-       case SRB_STATUS_TIMEOUT:
-               scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
-               break;
+               case SRB_STATUS_COMMAND_TIMEOUT:
+               case SRB_STATUS_TIMEOUT:
+                       scsicmd->result = DID_TIME_OUT << 16
+                                               | COMMAND_COMPLETE << 8;
+                       break;
 
-       case SRB_STATUS_BUSY:
-               scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
-               break;
+               case SRB_STATUS_BUSY:
+                       scsicmd->result = DID_BUS_BUSY << 16
+                                               | COMMAND_COMPLETE << 8;
+                       break;
 
-       case SRB_STATUS_BUS_RESET:
-               scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
-               break;
+               case SRB_STATUS_BUS_RESET:
+                       scsicmd->result = DID_RESET << 16
+                                               | COMMAND_COMPLETE << 8;
+                       break;
 
-       case SRB_STATUS_MESSAGE_REJECTED:
-               scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
-               break;
-       case SRB_STATUS_REQUEST_FLUSHED:
-       case SRB_STATUS_ERROR:
-       case SRB_STATUS_INVALID_REQUEST:
-       case SRB_STATUS_REQUEST_SENSE_FAILED:
-       case SRB_STATUS_NO_HBA:
-       case SRB_STATUS_UNEXPECTED_BUS_FREE:
-       case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
-       case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
-       case SRB_STATUS_DELAYED_RETRY:
-       case SRB_STATUS_BAD_FUNCTION:
-       case SRB_STATUS_NOT_STARTED:
-       case SRB_STATUS_NOT_IN_USE:
-       case SRB_STATUS_FORCE_ABORT:
-       case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
-       default:
+               case SRB_STATUS_MESSAGE_REJECTED:
+                       scsicmd->result = DID_ERROR << 16
+                                               | MESSAGE_REJECT << 8;
+                       break;
+               case SRB_STATUS_REQUEST_FLUSHED:
+               case SRB_STATUS_ERROR:
+               case SRB_STATUS_INVALID_REQUEST:
+               case SRB_STATUS_REQUEST_SENSE_FAILED:
+               case SRB_STATUS_NO_HBA:
+               case SRB_STATUS_UNEXPECTED_BUS_FREE:
+               case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
+               case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
+               case SRB_STATUS_DELAYED_RETRY:
+               case SRB_STATUS_BAD_FUNCTION:
+               case SRB_STATUS_NOT_STARTED:
+               case SRB_STATUS_NOT_IN_USE:
+               case SRB_STATUS_FORCE_ABORT:
+               case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
+               default:
 #ifdef AAC_DETAILED_STATUS_INFO
-               printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
-                       le32_to_cpu(srbreply->srb_status) & 0x3F,
-                       aac_get_status_string(
-                               le32_to_cpu(srbreply->srb_status) & 0x3F),
-                       scsicmd->cmnd[0],
-                       le32_to_cpu(srbreply->scsi_status));
+                       printk(KERN_INFO "aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
+                               le32_to_cpu(srbreply->srb_status) & 0x3F,
+                               aac_get_status_string(
+                                       le32_to_cpu(srbreply->srb_status) & 0x3F),
+                               scsicmd->cmnd[0],
+                               le32_to_cpu(srbreply->scsi_status));
 #endif
-               if ((scsicmd->cmnd[0] == ATA_12)
-                 || (scsicmd->cmnd[0] == ATA_16)) {
-                       if (scsicmd->cmnd[2] & (0x01 << 5)) {
-                               scsicmd->result = DID_OK << 16
-                                               | COMMAND_COMPLETE << 8;
+                       if ((scsicmd->cmnd[0] == ATA_12)
+                               || (scsicmd->cmnd[0] == ATA_16)) {
+                                       if (scsicmd->cmnd[2] & (0x01 << 5)) {
+                                               scsicmd->result = DID_OK << 16
+                                                       | COMMAND_COMPLETE << 8;
                                break;
+                               } else {
+                                       scsicmd->result = DID_ERROR << 16
+                                               | COMMAND_COMPLETE << 8;
+                                       break;
+                               }
                        } else {
                                scsicmd->result = DID_ERROR << 16
-                                               | COMMAND_COMPLETE << 8;
+                                       | COMMAND_COMPLETE << 8;
                                break;
                        }
-               } else {
-                       scsicmd->result = DID_ERROR << 16
-                                       | COMMAND_COMPLETE << 8;
-                       break;
                }
-       }
-       if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
-               int len;
-               scsicmd->result |= SAM_STAT_CHECK_CONDITION;
-               len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
-                           SCSI_SENSE_BUFFERSIZE);
+               if (le32_to_cpu(srbreply->scsi_status)
+                               == SAM_STAT_CHECK_CONDITION) {
+                       int len;
+
+                       scsicmd->result |= SAM_STAT_CHECK_CONDITION;
+                       len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
+                                   SCSI_SENSE_BUFFERSIZE);
 #ifdef AAC_DETAILED_STATUS_INFO
-               printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
-                                       le32_to_cpu(srbreply->status), len);
+                       printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
+                                               le32_to_cpu(srbreply->status), len);
 #endif
-               memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
+                       memcpy(scsicmd->sense_buffer,
+                                       srbreply->sense_data, len);
+               }
        }
        /*
         * OR in the scsi status (already shifted up a bit)
index 40fe65c91b416d1d8781b163e18299db5d76a13f..074878b55a0b7d9f371fe5bc57b2714e01074fdb 100644 (file)
@@ -12,7 +12,7 @@
  *              D E F I N E S
  *----------------------------------------------------------------------------*/
 
-#define AAC_MAX_MSIX                 /* vectors */
+#define AAC_MAX_MSIX           32      /* vectors */
 #define AAC_PCI_MSI_ENABLE     0x8000
 
 enum {
@@ -62,7 +62,7 @@ enum {
 #define        PMC_GLOBAL_INT_BIT0             0x00000001
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 40709
+# define AAC_DRIVER_BUILD 41010
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS 32
@@ -547,6 +547,7 @@ struct adapter_ops
        int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
        int  (*adapter_check_health)(struct aac_dev *dev);
        int  (*adapter_restart)(struct aac_dev *dev, int bled);
+       void (*adapter_start)(struct aac_dev *dev);
        /* Transport operations */
        int  (*adapter_ioremap)(struct aac_dev * dev, u32 size);
        irq_handler_t adapter_intr;
@@ -843,6 +844,10 @@ struct src_registers {
                                                &((AEP)->regs.src.bar0->CSR))
 #define src_writel(AEP, CSR, value)    writel(value, \
                                                &((AEP)->regs.src.bar0->CSR))
+#if defined(writeq)
+#define        src_writeq(AEP, CSR, value)     writeq(value, \
+                                               &((AEP)->regs.src.bar0->CSR))
+#endif
 
 #define SRC_ODR_SHIFT          12
 #define SRC_IDR_SHIFT          9
@@ -1162,6 +1167,11 @@ struct aac_dev
        struct fsa_dev_info     *fsa_dev;
        struct task_struct      *thread;
        int                     cardtype;
+       /*
+        *This lock will protect the two 32-bit
+        *writes to the Inbound Queue
+        */
+       spinlock_t              iq_lock;
 
        /*
         *      The following is the device specific extension.
@@ -1247,6 +1257,9 @@ struct aac_dev
 #define aac_adapter_restart(dev,bled) \
        (dev)->a_ops.adapter_restart(dev,bled)
 
+#define aac_adapter_start(dev) \
+       ((dev)->a_ops.adapter_start(dev))
+
 #define aac_adapter_ioremap(dev, size) \
        (dev)->a_ops.adapter_ioremap(dev, size)
 
@@ -2097,6 +2110,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
 #define AAC_OWNER_ERROR_HANDLER        0x103
 #define AAC_OWNER_FIRMWARE     0x106
 
+int aac_acquire_irq(struct aac_dev *dev);
+void aac_free_irq(struct aac_dev *dev);
 const char *aac_driverinfo(struct Scsi_Host *);
 struct fib *aac_fib_alloc(struct aac_dev *dev);
 int aac_fib_setup(struct aac_dev *dev);
@@ -2127,6 +2142,7 @@ int aac_sa_init(struct aac_dev *dev);
 int aac_src_init(struct aac_dev *dev);
 int aac_srcv_init(struct aac_dev *dev);
 int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
+void aac_define_int_mode(struct aac_dev *dev);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
 unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
index 45db84ad322f20de892a16e675acd3da6b8cbe84..0e954e37f0b5f3923980ee684e55ffef5b296510 100644 (file)
@@ -43,8 +43,6 @@
 
 #include "aacraid.h"
 
-static void aac_define_int_mode(struct aac_dev *dev);
-
 struct aac_common aac_config = {
        .irq_mod = 1
 };
@@ -338,6 +336,74 @@ static int aac_comm_init(struct aac_dev * dev)
        return 0;
 }
 
+void aac_define_int_mode(struct aac_dev *dev)
+{
+       int i, msi_count, min_msix;
+
+       msi_count = i = 0;
+       /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
+       if (dev->max_msix == 0 ||
+           dev->pdev->device == PMC_DEVICE_S6 ||
+           dev->sync_mode) {
+               dev->max_msix = 1;
+               dev->vector_cap =
+                       dev->scsi_host_ptr->can_queue +
+                       AAC_NUM_MGT_FIB;
+               return;
+       }
+
+       /* Don't bother allocating more MSI-X vectors than cpus */
+       msi_count = min(dev->max_msix,
+               (unsigned int)num_online_cpus());
+
+       dev->max_msix = msi_count;
+
+       if (msi_count > AAC_MAX_MSIX)
+               msi_count = AAC_MAX_MSIX;
+
+       for (i = 0; i < msi_count; i++)
+               dev->msixentry[i].entry = i;
+
+       if (msi_count > 1 &&
+           pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
+               min_msix = 2;
+               i = pci_enable_msix_range(dev->pdev,
+                                   dev->msixentry,
+                                   min_msix,
+                                   msi_count);
+               if (i > 0) {
+                       dev->msi_enabled = 1;
+                       msi_count = i;
+               } else {
+                       dev->msi_enabled = 0;
+                       printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
+                                       dev->name, dev->id, i);
+               }
+       }
+
+       if (!dev->msi_enabled) {
+               msi_count = 1;
+               i = pci_enable_msi(dev->pdev);
+
+               if (!i) {
+                       dev->msi_enabled = 1;
+                       dev->msi = 1;
+               } else {
+                       printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
+                                       dev->name, dev->id, i);
+               }
+       }
+
+       if (!dev->msi_enabled)
+               dev->max_msix = msi_count = 1;
+       else {
+               if (dev->max_msix > msi_count)
+                       dev->max_msix = msi_count;
+       }
+       dev->vector_cap =
+               (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
+               msi_count;
+}
 struct aac_dev *aac_init_adapter(struct aac_dev *dev)
 {
        u32 status[5];
@@ -350,6 +416,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
        dev->management_fib_count = 0;
        spin_lock_init(&dev->manage_lock);
        spin_lock_init(&dev->sync_lock);
+       spin_lock_init(&dev->iq_lock);
        dev->max_fib_size = sizeof(struct hw_fib);
        dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
                - sizeof(struct aac_fibhdr)
@@ -508,79 +575,3 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
        return dev;
 }
 
-static void aac_define_int_mode(struct aac_dev *dev)
-{
-
-       int i, msi_count;
-
-       msi_count = i = 0;
-       /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
-       if (dev->max_msix == 0 ||
-           dev->pdev->device == PMC_DEVICE_S6 ||
-           dev->sync_mode) {
-               dev->max_msix = 1;
-               dev->vector_cap =
-                       dev->scsi_host_ptr->can_queue +
-                       AAC_NUM_MGT_FIB;
-               return;
-       }
-
-       msi_count = min(dev->max_msix,
-               (unsigned int)num_online_cpus());
-
-       dev->max_msix = msi_count;
-
-       if (msi_count > AAC_MAX_MSIX)
-               msi_count = AAC_MAX_MSIX;
-
-       for (i = 0; i < msi_count; i++)
-               dev->msixentry[i].entry = i;
-
-       if (msi_count > 1 &&
-           pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
-               i = pci_enable_msix(dev->pdev,
-                                   dev->msixentry,
-                                   msi_count);
-                /* Check how many MSIX vectors are allocated */
-               if (i >= 0) {
-                       dev->msi_enabled = 1;
-                       if (i) {
-                               msi_count = i;
-                               if (pci_enable_msix(dev->pdev,
-                                   dev->msixentry,
-                                   msi_count)) {
-                                       dev->msi_enabled = 0;
-                                       printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
-                                                       dev->name, dev->id, i);
-                               }
-                       }
-               } else {
-                       dev->msi_enabled = 0;
-                       printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
-                                       dev->name, dev->id, i);
-               }
-       }
-
-       if (!dev->msi_enabled) {
-               msi_count = 1;
-               i = pci_enable_msi(dev->pdev);
-
-               if (!i) {
-                       dev->msi_enabled = 1;
-                       dev->msi = 1;
-               } else {
-                       printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
-                                       dev->name, dev->id, i);
-               }
-       }
-
-       if (!dev->msi_enabled)
-               dev->max_msix = msi_count = 1;
-       else {
-               if (dev->max_msix > msi_count)
-                       dev->max_msix = msi_count;
-       }
-       dev->vector_cap =
-               (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
-               msi_count;
-}
index 4da574925284454cdba9cd6d6cc036bffc3dcdea..a1f90fe849c95201f410972b34413f45e484802e 100644 (file)
@@ -1270,13 +1270,12 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
 static int _aac_reset_adapter(struct aac_dev *aac, int forced)
 {
        int index, quirks;
-       int retval, i;
+       int retval;
        struct Scsi_Host *host;
        struct scsi_device *dev;
        struct scsi_cmnd *command;
        struct scsi_cmnd *command_list;
        int jafo = 0;
-       int cpu;
 
        /*
         * Assumptions:
@@ -1339,35 +1338,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
        aac->comm_phys = 0;
        kfree(aac->queues);
        aac->queues = NULL;
-       cpu = cpumask_first(cpu_online_mask);
-       if (aac->pdev->device == PMC_DEVICE_S6 ||
-           aac->pdev->device == PMC_DEVICE_S7 ||
-           aac->pdev->device == PMC_DEVICE_S8 ||
-           aac->pdev->device == PMC_DEVICE_S9) {
-               if (aac->max_msix > 1) {
-                       for (i = 0; i < aac->max_msix; i++) {
-                               if (irq_set_affinity_hint(
-                                   aac->msixentry[i].vector,
-                                   NULL)) {
-                                       printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
-                                               aac->name,
-                                               aac->id,
-                                               cpu);
-                               }
-                               cpu = cpumask_next(cpu,
-                                               cpu_online_mask);
-                               free_irq(aac->msixentry[i].vector,
-                                        &(aac->aac_msix[i]));
-                       }
-                       pci_disable_msix(aac->pdev);
-               } else {
-                       free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
-               }
-       } else {
-               free_irq(aac->pdev->irq, aac);
-       }
-       if (aac->msi)
-               pci_disable_msi(aac->pdev);
+       aac_free_irq(aac);
        kfree(aac->fsa_dev);
        aac->fsa_dev = NULL;
        quirks = aac_get_driver_ident(index)->quirks;
@@ -1978,3 +1949,83 @@ int aac_command_thread(void *data)
        dev->aif_thread = 0;
        return 0;
 }
+
+int aac_acquire_irq(struct aac_dev *dev)
+{
+       int i;
+       int j;
+       int ret = 0;
+       int cpu;
+
+       cpu = cpumask_first(cpu_online_mask);
+       if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+               for (i = 0; i < dev->max_msix; i++) {
+                       dev->aac_msix[i].vector_no = i;
+                       dev->aac_msix[i].dev = dev;
+                       if (request_irq(dev->msixentry[i].vector,
+                                       dev->a_ops.adapter_intr,
+                                       0, "aacraid", &(dev->aac_msix[i]))) {
+                               printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
+                                               dev->name, dev->id, i);
+                               for (j = 0 ; j < i ; j++)
+                                       free_irq(dev->msixentry[j].vector,
+                                                &(dev->aac_msix[j]));
+                               pci_disable_msix(dev->pdev);
+                               ret = -1;
+                       }
+                       if (irq_set_affinity_hint(dev->msixentry[i].vector,
+                                                       get_cpu_mask(cpu))) {
+                               printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
+                                           dev->name, dev->id, cpu);
+                       }
+                       cpu = cpumask_next(cpu, cpu_online_mask);
+               }
+       } else {
+               dev->aac_msix[0].vector_no = 0;
+               dev->aac_msix[0].dev = dev;
+
+               if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+                       IRQF_SHARED, "aacraid",
+                       &(dev->aac_msix[0])) < 0) {
+                       if (dev->msi)
+                               pci_disable_msi(dev->pdev);
+                       printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+                                       dev->name, dev->id);
+                       ret = -1;
+               }
+       }
+       return ret;
+}
+
+void aac_free_irq(struct aac_dev *dev)
+{
+       int i;
+       int cpu;
+
+       cpu = cpumask_first(cpu_online_mask);
+       if (dev->pdev->device == PMC_DEVICE_S6 ||
+           dev->pdev->device == PMC_DEVICE_S7 ||
+           dev->pdev->device == PMC_DEVICE_S8 ||
+           dev->pdev->device == PMC_DEVICE_S9) {
+               if (dev->max_msix > 1) {
+                       for (i = 0; i < dev->max_msix; i++) {
+                               if (irq_set_affinity_hint(
+                                       dev->msixentry[i].vector, NULL)) {
+                                       printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
+                                           dev->name, dev->id, cpu);
+                               }
+                               cpu = cpumask_next(cpu, cpu_online_mask);
+                               free_irq(dev->msixentry[i].vector,
+                                               &(dev->aac_msix[i]));
+                       }
+               } else {
+                       free_irq(dev->pdev->irq, &(dev->aac_msix[0]));
+               }
+       } else {
+               free_irq(dev->pdev->irq, dev);
+       }
+       if (dev->msi)
+               pci_disable_msi(dev->pdev);
+       else if (dev->max_msix > 1)
+               pci_disable_msix(dev->pdev);
+}
index 9eec02733c8656e818efa8574652859e65ebad94..3b6e5c67e853d96aeafeee16859d19bfa3731a5b 100644 (file)
@@ -1317,6 +1317,154 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return error;
 }
 
+#if (defined(CONFIG_PM))
+void aac_release_resources(struct aac_dev *aac)
+{
+       int i;
+
+       aac_adapter_disable_int(aac);
+       if (aac->pdev->device == PMC_DEVICE_S6 ||
+           aac->pdev->device == PMC_DEVICE_S7 ||
+           aac->pdev->device == PMC_DEVICE_S8 ||
+           aac->pdev->device == PMC_DEVICE_S9) {
+               if (aac->max_msix > 1) {
+                       for (i = 0; i < aac->max_msix; i++)
+                               free_irq(aac->msixentry[i].vector,
+                                       &(aac->aac_msix[i]));
+               } else {
+                       free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
+               }
+       } else {
+               free_irq(aac->pdev->irq, aac);
+       }
+       if (aac->msi)
+               pci_disable_msi(aac->pdev);
+       else if (aac->max_msix > 1)
+               pci_disable_msix(aac->pdev);
+
+}
+
+static int aac_acquire_resources(struct aac_dev *dev)
+{
+       int i, j;
+       int instance = dev->id;
+       const char *name = dev->name;
+       unsigned long status;
+       /*
+        *      First clear out all interrupts.  Then enable the one's that we
+        *      can handle.
+        */
+       while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)
+               || status == 0xffffffff)
+                       msleep(20);
+
+       aac_adapter_disable_int(dev);
+       aac_adapter_enable_int(dev);
+
+
+       if ((dev->pdev->device == PMC_DEVICE_S7 ||
+            dev->pdev->device == PMC_DEVICE_S8 ||
+            dev->pdev->device == PMC_DEVICE_S9))
+               aac_define_int_mode(dev);
+
+       if (dev->msi_enabled)
+               aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
+
+       if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+               for (i = 0; i < dev->max_msix; i++) {
+                       dev->aac_msix[i].vector_no = i;
+                       dev->aac_msix[i].dev = dev;
+
+                       if (request_irq(dev->msixentry[i].vector,
+                                       dev->a_ops.adapter_intr,
+                                       0, "aacraid", &(dev->aac_msix[i]))) {
+                               printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
+                                               name, instance, i);
+                               for (j = 0 ; j < i ; j++)
+                                       free_irq(dev->msixentry[j].vector,
+                                                &(dev->aac_msix[j]));
+                               pci_disable_msix(dev->pdev);
+                               goto error_iounmap;
+                       }
+               }
+       } else {
+               dev->aac_msix[0].vector_no = 0;
+               dev->aac_msix[0].dev = dev;
+
+               if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+                       IRQF_SHARED, "aacraid",
+                       &(dev->aac_msix[0])) < 0) {
+                       if (dev->msi)
+                               pci_disable_msi(dev->pdev);
+                       printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+                                       name, instance);
+                       goto error_iounmap;
+               }
+       }
+
+       aac_adapter_enable_int(dev);
+
+       if (!dev->sync_mode)
+               aac_adapter_start(dev);
+       return 0;
+
+error_iounmap:
+       return -1;
+
+}
+static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+
+       scsi_block_requests(shost);
+       aac_send_shutdown(aac);
+
+       aac_release_resources(aac);
+
+       pci_set_drvdata(pdev, shost);
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int aac_resume(struct pci_dev *pdev)
+{
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+       int r;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_enable_wake(pdev, PCI_D0, 0);
+       pci_restore_state(pdev);
+       r = pci_enable_device(pdev);
+
+       if (r)
+               goto fail_device;
+
+       pci_set_master(pdev);
+       if (aac_acquire_resources(aac))
+               goto fail_device;
+       /*
+       * reset this flag to unblock ioctl() as it was set at
+       * aac_send_shutdown() to block ioctls from upperlayer
+       */
+       aac->adapter_shutdown = 0;
+       scsi_unblock_requests(shost);
+
+       return 0;
+
+fail_device:
+       printk(KERN_INFO "%s%d: resume failed.\n", aac->name, aac->id);
+       scsi_host_put(shost);
+       pci_disable_device(pdev);
+       return -ENODEV;
+}
+#endif
+
 static void aac_shutdown(struct pci_dev *dev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(dev);
@@ -1356,6 +1504,10 @@ static struct pci_driver aac_pci_driver = {
        .id_table       = aac_pci_tbl,
        .probe          = aac_probe_one,
        .remove         = aac_remove_one,
+#if (defined(CONFIG_PM))
+       .suspend        = aac_suspend,
+       .resume         = aac_resume,
+#endif
        .shutdown       = aac_shutdown,
 };
 
index 9570612b80ce1eedfea7ee46881030141efb9b2c..ac1638069335a66e87b4ccfb5da9d323c2ef6b50 100644 (file)
@@ -623,6 +623,7 @@ int _aac_rx_init(struct aac_dev *dev)
        dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
        dev->a_ops.adapter_check_health = aac_rx_check_health;
        dev->a_ops.adapter_restart = aac_rx_restart_adapter;
+       dev->a_ops.adapter_start = aac_rx_start_adapter;
 
        /*
         *      First clear out all interrupts.  Then enable the one's that we
index e66477c98240e40f9c6aae11b59cb61da2aa41f3..869aea23c0411be51ff270bc8d140ed6fce254e1 100644 (file)
@@ -372,6 +372,7 @@ int aac_sa_init(struct aac_dev *dev)
        dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
        dev->a_ops.adapter_check_health = aac_sa_check_health;
        dev->a_ops.adapter_restart = aac_sa_restart_adapter;
+       dev->a_ops.adapter_start = aac_sa_start_adapter;
        dev->a_ops.adapter_intr = aac_sa_intr;
        dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
        dev->a_ops.adapter_ioremap = aac_sa_ioremap;
index e63cf9f22f36a40f2e4bf1320cbc695e5a40812e..2aa34ea8ceb1e903781331acd3283ba264eadd53 100644 (file)
@@ -447,6 +447,10 @@ static int aac_src_deliver_message(struct fib *fib)
        u32 fibsize;
        dma_addr_t address;
        struct aac_fib_xporthdr *pFibX;
+#if !defined(writeq)
+       unsigned long flags;
+#endif
+
        u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
 
        atomic_inc(&q->numpending);
@@ -511,10 +515,14 @@ static int aac_src_deliver_message(struct fib *fib)
                        return -EINVAL;
                address |= fibsize;
        }
-
+#if defined(writeq)
+       src_writeq(dev, MUnit.IQ_L, (u64)address);
+#else
+       spin_lock_irqsave(&fib->dev->iq_lock, flags);
        src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff);
        src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
-
+       spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
+#endif
        return 0;
 }
 
@@ -726,6 +734,7 @@ int aac_src_init(struct aac_dev *dev)
        dev->a_ops.adapter_sync_cmd = src_sync_cmd;
        dev->a_ops.adapter_check_health = aac_src_check_health;
        dev->a_ops.adapter_restart = aac_src_restart_adapter;
+       dev->a_ops.adapter_start = aac_src_start_adapter;
 
        /*
         *      First clear out all interrupts.  Then enable the one's that we
@@ -741,7 +750,7 @@ int aac_src_init(struct aac_dev *dev)
        if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
                goto error_iounmap;
 
-       dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
+       dev->msi = !pci_enable_msi(dev->pdev);
 
        dev->aac_msix[0].vector_no = 0;
        dev->aac_msix[0].dev = dev;
@@ -789,9 +798,7 @@ int aac_srcv_init(struct aac_dev *dev)
        unsigned long status;
        int restart = 0;
        int instance = dev->id;
-       int i, j;
        const char *name = dev->name;
-       int cpu;
 
        dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
        dev->a_ops.adapter_comm = aac_src_select_comm;
@@ -892,6 +899,7 @@ int aac_srcv_init(struct aac_dev *dev)
        dev->a_ops.adapter_sync_cmd = src_sync_cmd;
        dev->a_ops.adapter_check_health = aac_src_check_health;
        dev->a_ops.adapter_restart = aac_src_restart_adapter;
+       dev->a_ops.adapter_start = aac_src_start_adapter;
 
        /*
         *      First clear out all interrupts.  Then enable the one's that we
@@ -908,48 +916,10 @@ int aac_srcv_init(struct aac_dev *dev)
                goto error_iounmap;
        if (dev->msi_enabled)
                aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
-       if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
-               cpu = cpumask_first(cpu_online_mask);
-               for (i = 0; i < dev->max_msix; i++) {
-                       dev->aac_msix[i].vector_no = i;
-                       dev->aac_msix[i].dev = dev;
-
-                       if (request_irq(dev->msixentry[i].vector,
-                                       dev->a_ops.adapter_intr,
-                                       0,
-                                       "aacraid",
-                                       &(dev->aac_msix[i]))) {
-                               printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
-                                               name, instance, i);
-                               for (j = 0 ; j < i ; j++)
-                                       free_irq(dev->msixentry[j].vector,
-                                                &(dev->aac_msix[j]));
-                               pci_disable_msix(dev->pdev);
-                               goto error_iounmap;
-                       }
-                       if (irq_set_affinity_hint(
-                          dev->msixentry[i].vector,
-                          get_cpu_mask(cpu))) {
-                               printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
-                                               name, instance, cpu);
-                       }
-                       cpu = cpumask_next(cpu, cpu_online_mask);
-               }
-       } else {
-               dev->aac_msix[0].vector_no = 0;
-               dev->aac_msix[0].dev = dev;
-
-               if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
-                               IRQF_SHARED,
-                               "aacraid",
-                               &(dev->aac_msix[0])) < 0) {
-                       if (dev->msi)
-                               pci_disable_msi(dev->pdev);
-                       printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
-                                       name, instance);
-                       goto error_iounmap;
-               }
-       }
+
+       if (aac_acquire_irq(dev))
+               goto error_iounmap;
+
        dev->dbg_base = dev->base_start;
        dev->dbg_base_mapped = dev->base;
        dev->dbg_size = dev->base_size;
index 4305178e4e0147ba9a8f8e04a452e77947f2cddb..519f9a4b3dadf39c07be7e61f20fc2481cddbd02 100644 (file)
@@ -10819,7 +10819,6 @@ static struct scsi_host_template advansys_template = {
         * by enabling clustering, I/O throughput increases as well.
         */
        .use_clustering = ENABLE_CLUSTERING,
-       .use_blk_tags = 1,
 };
 
 static int advansys_wide_init_chip(struct Scsi_Host *shost)
@@ -11211,11 +11210,6 @@ static int advansys_board_found(struct Scsi_Host *shost, unsigned int iop,
                /* Set maximum number of queues the adapter can handle. */
                shost->can_queue = adv_dvc_varp->max_host_qng;
        }
-       ret = scsi_init_shared_tag_map(shost, shost->can_queue);
-       if (ret) {
-               shost_printk(KERN_ERR, shost, "init tag map failed\n");
-               goto err_free_dma;
-       }
 
        /*
         * Set the maximum number of scatter-gather elements the
index ce96a0be32820fa6b75460adf9e4b7f48587ab05..2588b8f84ba0ec37108f3bfedb033cee44c47985 100644 (file)
@@ -925,7 +925,6 @@ struct scsi_host_template aic79xx_driver_template = {
        .slave_configure        = ahd_linux_slave_configure,
        .target_alloc           = ahd_linux_target_alloc,
        .target_destroy         = ahd_linux_target_destroy,
-       .use_blk_tags           = 1,
 };
 
 /******************************** Bus DMA *************************************/
index a2f2c774cd6b75f5874d71b5970a739a6923abaa..b846a4683562ca8ddd472becdb70a9a3d56387bf 100644 (file)
@@ -812,7 +812,6 @@ struct scsi_host_template aic7xxx_driver_template = {
        .slave_configure        = ahc_linux_slave_configure,
        .target_alloc           = ahc_linux_target_alloc,
        .target_destroy         = ahc_linux_target_destroy,
-       .use_blk_tags           = 1,
 };
 
 /**************************** Tasklet Handler *********************************/
index f6c336b05d5bbf6e0354c3f18697fd3350f3d09e..662b2321d1b0f40e73bf401925e23b81d377462a 100644 (file)
@@ -73,7 +73,6 @@ static struct scsi_host_template aic94xx_sht = {
        .eh_bus_reset_handler   = sas_eh_bus_reset_handler,
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -704,10 +703,10 @@ static int asd_unregister_sas_ha(struct asd_ha_struct *asd_ha)
 {
        int err;
 
+       scsi_remove_host(asd_ha->sas_ha.core.shost);
        err = sas_unregister_ha(&asd_ha->sas_ha);
 
        sas_remove_host(asd_ha->sas_ha.core.shost);
-       scsi_remove_host(asd_ha->sas_ha.core.shost);
        scsi_host_put(asd_ha->sas_ha.core.shost);
 
        kfree(asd_ha->sas_ha.sas_phy);
index 2e6abe7b73241b4bbbfa88a4bf97f7c672bcef61..fe0c5143f8e68a6cb3e9618c98258c9e4118e1ae 100644 (file)
@@ -1198,14 +1198,16 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
  * alloc_wrb_handle - To allocate a wrb handle
  * @phba: The hba pointer
  * @cid: The cid to use for allocation
+ * @pwrb_context: ptr to ptr to wrb context
  *
  * This happens under session_lock until submission to chip
  */
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                    struct hwi_wrb_context **pcontext)
 {
        struct hwi_wrb_context *pwrb_context;
        struct hwi_controller *phwi_ctrlr;
-       struct wrb_handle *pwrb_handle, *pwrb_handle_tmp;
+       struct wrb_handle *pwrb_handle;
        uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
 
        phwi_ctrlr = phba->phwi_ctrlr;
@@ -1219,9 +1221,9 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)
                        pwrb_context->alloc_index = 0;
                else
                        pwrb_context->alloc_index++;
-               pwrb_handle_tmp = pwrb_context->pwrb_handle_base[
-                                               pwrb_context->alloc_index];
-               pwrb_handle->nxt_wrb_index = pwrb_handle_tmp->wrb_index;
+
+               /* Return the context address */
+               *pcontext = pwrb_context;
        } else
                pwrb_handle = NULL;
        return pwrb_handle;
@@ -3184,7 +3186,7 @@ be_sgl_create_contiguous(void *virtual_address,
 {
        WARN_ON(!virtual_address);
        WARN_ON(!physical_address);
-       WARN_ON(!length > 0);
+       WARN_ON(!length);
        WARN_ON(!sgl);
 
        sgl->va = virtual_address;
@@ -4678,6 +4680,7 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
                           struct beiscsi_offload_params *params)
 {
        struct wrb_handle *pwrb_handle;
+       struct hwi_wrb_context *pwrb_context = NULL;
        struct beiscsi_hba *phba = beiscsi_conn->phba;
        struct iscsi_task *task = beiscsi_conn->task;
        struct iscsi_session *session = task->conn->session;
@@ -4692,14 +4695,17 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
        beiscsi_cleanup_task(task);
        spin_unlock_bh(&session->back_lock);
 
-       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid);
+       pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid,
+                                      &pwrb_context);
 
        /* Check for the adapter family */
        if (is_chip_be2_be3r(phba))
                beiscsi_offload_cxn_v0(params, pwrb_handle,
-                                      phba->init_mem);
+                                      phba->init_mem,
+                                      pwrb_context);
        else
-               beiscsi_offload_cxn_v2(params, pwrb_handle);
+               beiscsi_offload_cxn_v2(params, pwrb_handle,
+                                      pwrb_context);
 
        be_dws_le_to_cpu(pwrb_handle->pwrb,
                         sizeof(struct iscsi_target_context_update_wrb));
@@ -4769,7 +4775,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        goto free_hndls;
                }
                io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                if (!io_task->pwrb_handle) {
                        beiscsi_log(phba, KERN_ERR,
                                    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4803,7 +4810,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                                        io_task->psgl_handle;
                                io_task->pwrb_handle =
                                        alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                                if (!io_task->pwrb_handle) {
                                        beiscsi_log(phba, KERN_ERR,
                                                    BEISCSI_LOG_IO |
@@ -4839,7 +4847,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        }
                        io_task->pwrb_handle =
                                        alloc_wrb_handle(phba,
-                                       beiscsi_conn->beiscsi_conn_cid);
+                                       beiscsi_conn->beiscsi_conn_cid,
+                                       &io_task->pwrb_context);
                        if (!io_task->pwrb_handle) {
                                beiscsi_log(phba, KERN_ERR,
                                            BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@@ -4925,7 +4934,12 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
 
        hwi_write_sgl_v2(pwrb, sg, num_sg, io_task);
        AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
-                     io_task->pwrb_handle->nxt_wrb_index);
+                     io_task->pwrb_handle->wrb_index);
+       if (io_task->pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+                             io_task->pwrb_context->plast_wrb,
+                             io_task->pwrb_handle->wrb_index);
+       io_task->pwrb_context->plast_wrb = pwrb;
 
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
 
@@ -4982,7 +4996,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
        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);
+                     io_task->pwrb_handle->wrb_index);
+       if (io_task->pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+                             io_task->pwrb_context->plast_wrb,
+                             io_task->pwrb_handle->wrb_index);
+       io_task->pwrb_context->plast_wrb = pwrb;
+
        be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb));
 
        doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;
@@ -5020,7 +5040,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
                AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb,
                              task->data_count);
                AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb,
-                             io_task->pwrb_handle->nxt_wrb_index);
+                             io_task->pwrb_handle->wrb_index);
+               if (io_task->pwrb_context->plast_wrb)
+                       AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb,
+                                     io_task->pwrb_context->plast_wrb,
+                                     io_task->pwrb_handle->wrb_index);
+               io_task->pwrb_context->plast_wrb = pwrb;
+
                pwrb_typeoffset = BE_WRB_TYPE_OFFSET;
        } else {
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb,
@@ -5032,7 +5058,13 @@ static int beiscsi_mtask(struct iscsi_task *task)
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb,
                              task->data_count);
                AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb,
-                             io_task->pwrb_handle->nxt_wrb_index);
+                             io_task->pwrb_handle->wrb_index);
+               if (io_task->pwrb_context->plast_wrb)
+                       AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb,
+                                     io_task->pwrb_context->plast_wrb,
+                                     io_task->pwrb_handle->wrb_index);
+               io_task->pwrb_context->plast_wrb = pwrb;
+
                pwrb_typeoffset = SKH_WRB_TYPE_OFFSET;
        }
 
index 51366de5ef702661d5c94aadb87b444b743548cb..5c67c0732241b507e199ff756ad1c60e17c0b703 100644 (file)
@@ -36,7 +36,7 @@
 #include <scsi/scsi_transport_iscsi.h>
 
 #define DRV_NAME               "be2iscsi"
-#define BUILD_STR              "10.6.0.0"
+#define BUILD_STR              "10.6.0.1"
 #define BE_NAME                        "Emulex OneConnect" \
                                "Open-iSCSI Driver version" BUILD_STR
 #define DRV_DESC               BE_NAME " " "Driver"
@@ -502,6 +502,7 @@ struct beiscsi_io_task {
        struct sgl_handle *psgl_handle;
        struct beiscsi_conn *conn;
        struct scsi_cmnd *scsi_cmnd;
+       struct hwi_wrb_context *pwrb_context;
        unsigned int cmd_sn;
        unsigned int flags;
        unsigned short cid;
@@ -833,7 +834,8 @@ struct amap_iscsi_wrb_v2 {
 } __packed;
 
 
-struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid);
+struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
+                                    struct hwi_wrb_context **pcontext);
 void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle);
 
@@ -1044,7 +1046,6 @@ enum hwh_type_enum {
 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;
index 1b2bd044dad6dacc4ef81a4298ac80c7071493a3..aea3e6b9477dcc73df18b263365609a93abd3758 100644 (file)
@@ -1573,7 +1573,8 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
 
 void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                             struct wrb_handle *pwrb_handle,
-                            struct be_mem_descriptor *mem_descr)
+                            struct be_mem_descriptor *mem_descr,
+                            struct hwi_wrb_context *pwrb_context)
 {
        struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
@@ -1617,7 +1618,14 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                      max_burst_length) / 32]);
 
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb,
-                     pwrb, pwrb_handle->nxt_wrb_index);
+                     pwrb, pwrb_handle->wrb_index);
+       if (pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb,
+                             ptr2nextwrb,
+                             pwrb_context->plast_wrb,
+                             pwrb_handle->wrb_index);
+       pwrb_context->plast_wrb = pwrb;
+
        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,
@@ -1637,7 +1645,8 @@ void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
 }
 
 void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
-                            struct wrb_handle *pwrb_handle)
+                            struct wrb_handle *pwrb_handle,
+                            struct hwi_wrb_context *pwrb_context)
 {
        struct iscsi_wrb *pwrb = pwrb_handle->pwrb;
 
@@ -1652,7 +1661,14 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
                      BE_TGT_CTX_UPDT_CMD);
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
                      ptr2nextwrb,
-                     pwrb, pwrb_handle->nxt_wrb_index);
+                     pwrb, pwrb_handle->wrb_index);
+       if (pwrb_context->plast_wrb)
+               AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
+                             ptr2nextwrb,
+                             pwrb_context->plast_wrb,
+                             pwrb_handle->wrb_index);
+       pwrb_context->plast_wrb = pwrb;
+
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2, wrb_idx,
                      pwrb, pwrb_handle->wrb_index);
        AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb_v2,
index afa326da75c6797d3a06126e2e5e8921f03f5da9..c1dbb690ee279f669fffb2ddab5919189923b8c8 100644 (file)
@@ -330,10 +330,13 @@ ssize_t beiscsi_phys_port_disp(struct device *dev,
 
 void beiscsi_offload_cxn_v0(struct beiscsi_offload_params *params,
                             struct wrb_handle *pwrb_handle,
-                            struct be_mem_descriptor *mem_descr);
+                            struct be_mem_descriptor *mem_descr,
+                            struct hwi_wrb_context *pwrb_context);
 
 void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
-                            struct wrb_handle *pwrb_handle);
+                            struct wrb_handle *pwrb_handle,
+                            struct hwi_wrb_context *pwrb_context);
+
 void beiscsi_ue_detect(struct beiscsi_hba *phba);
 int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
                         struct be_set_eqd *, int num);
index 8367c11d554b22a6fb5b7c5385b56bbc7f156f45..299c6f80d4605116c5039cb1a23b77a0b4324d05 100644 (file)
@@ -800,7 +800,6 @@ struct scsi_host_template bfad_im_scsi_host_template = {
        .shost_attrs = bfad_im_host_attrs,
        .max_sectors = BFAD_MAX_SECTORS,
        .vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
-       .use_blk_tags = 1,
 };
 
 struct scsi_host_template bfad_im_vport_template = {
@@ -822,7 +821,6 @@ struct scsi_host_template bfad_im_vport_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = bfad_im_vport_attrs,
        .max_sectors = BFAD_MAX_SECTORS,
-       .use_blk_tags = 1,
 };
 
 bfa_status_t
index fe2106c91c08585049da46972d53f8089dc2469f..ac1c0b631acab02d5d78ed3ec5bd268a91b81785 100644 (file)
@@ -1,9 +1,9 @@
-/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* 57xx_hsi_bnx2fc.h: QLogic Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 0978828826498693f794f661f0a6dc0f9cde6170..d401a096dfc7eb517642a29ae4aa5f3862fb40e5 100644 (file)
@@ -1,5 +1,5 @@
 config SCSI_BNX2X_FCOE
-       tristate "QLogic NetXtreme II FCoE support"
+       tristate "QLogic FCoE offload support"
        depends on PCI
        depends on (IPV6 || IPV6=n)
        depends on LIBFC
@@ -9,5 +9,4 @@ config SCSI_BNX2X_FCOE
        select NET_VENDOR_BROADCOM
        select CNIC
        ---help---
-       This driver supports FCoE offload for the QLogic NetXtreme II
-       devices.
+       This driver supports FCoE offload for the QLogic devices.
index 1346e052e03cc1311792b8a4c9bf3c85565748a6..499e369eabf0bb165a4300373be7868fd896bd85 100644 (file)
@@ -1,7 +1,7 @@
-/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc.h: QLogic Linux FCoE offload driver.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -65,7 +65,7 @@
 #include "bnx2fc_constants.h"
 
 #define BNX2FC_NAME            "bnx2fc"
-#define BNX2FC_VERSION         "2.4.2"
+#define BNX2FC_VERSION         "2.9.6"
 
 #define PFX                    "bnx2fc: "
 
@@ -303,7 +303,6 @@ struct bnx2fc_rport {
 #define BNX2FC_FLAG_OFLD_REQ_CMPL      0x5
 #define BNX2FC_FLAG_CTX_ALLOC_FAILURE  0x6
 #define BNX2FC_FLAG_UPLD_REQ_COMPL     0x7
-#define BNX2FC_FLAG_EXPL_LOGO          0x8
 #define BNX2FC_FLAG_DISABLE_FAILED     0x9
 #define BNX2FC_FLAG_ENABLED            0xa
 
index e147cc7ee36c5d454de7967f0eabbee7abaf7187..5b20efb661a57ee9d89cbdfaa6a67122e276dc52 100644 (file)
@@ -1,9 +1,9 @@
-/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_constants.h: QLogic Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index d055df01faa5b3c18442e09a0806234459b0673e..c9e0bc7fad3b35af613b031b8aea76055a2fbadd 100644 (file)
@@ -1,9 +1,9 @@
-/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_debug.c: QLogic Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 2b9006774f377241565f36137dde0de616697376..34fda3e04d27024a8325191ec6fbf47c0e3a4a8f 100644 (file)
@@ -1,9 +1,9 @@
-/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_debug.h: QLogic Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index ef355c13ccc47c9a9f05cde438408e4e56b3eb3d..5beea776b9f54c3fe920c1f561f19fce001c4a56 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver.
+ * bnx2fc_els.c: QLogic Linux FCoE offload driver.
  * This file contains helper routines that handle ELS requests
  * and responses.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -689,8 +689,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
                rc = -EINVAL;
                goto els_err;
        }
-       if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
-            (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
+       if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
                printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
                rc = -EINVAL;
                goto els_err;
@@ -707,6 +706,7 @@ static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
        els_req->cb_func = cb_func;
        cb_arg->io_req = els_req;
        els_req->cb_arg = cb_arg;
+       els_req->data_xfer_len = data_len;
 
        mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
        rc = bnx2fc_init_mp_req(els_req);
index b0bc5ffee903ad8b497886c0c445700496630110..67405c628864875bab6e56beb2a67846fa690ead 100644 (file)
@@ -1,10 +1,10 @@
-/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_fcoe.c: QLogic Linux FCoE offload driver.
  * This file contains the code that interacts with libfc, libfcoe,
  * cnic modules to create FCoE instances, send/receive non-offloaded
  * FIP/FCoE packets, listen to link events etc.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,16 +23,16 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
 
 #define DRV_MODULE_NAME                "bnx2fc"
 #define DRV_MODULE_VERSION     BNX2FC_VERSION
-#define DRV_MODULE_RELDATE     "Dec 11, 2013"
+#define DRV_MODULE_RELDATE     "October 15, 2015"
 
 
 static char version[] =
-               "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+               "QLogic FCoE Driver " DRV_MODULE_NAME \
                " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 
 MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
-MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver");
+MODULE_DESCRIPTION("QLogic FCoE Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
@@ -2091,7 +2091,7 @@ static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
 {
        struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr);
        struct bnx2fc_hba *hba;
-       struct cnic_fc_npiv_tbl npiv_tbl;
+       struct cnic_fc_npiv_tbl *npiv_tbl;
        struct fc_lport *lport;
 
        if (interface->enabled == false) {
@@ -2123,11 +2123,16 @@ static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
        if (!hba->cnic->get_fc_npiv_tbl)
                goto done;
 
-       memset(&npiv_tbl, 0, sizeof(npiv_tbl));
-       if (hba->cnic->get_fc_npiv_tbl(hba->cnic, &npiv_tbl))
+       npiv_tbl = kzalloc(sizeof(struct cnic_fc_npiv_tbl), GFP_KERNEL);
+       if (!npiv_tbl)
                goto done;
 
-       bnx2fc_npiv_create_vports(lport, &npiv_tbl);
+       if (hba->cnic->get_fc_npiv_tbl(hba->cnic, npiv_tbl))
+               goto done_free;
+
+       bnx2fc_npiv_create_vports(lport, npiv_tbl);
+done_free:
+       kfree(npiv_tbl);
 done:
        return 0;
 }
@@ -2862,7 +2867,6 @@ static struct scsi_host_template bnx2fc_shost_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .sg_tablesize           = BNX2FC_MAX_BDS_PER_CMD,
        .max_sectors            = 1024,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
index c6688d72a846fa61d37324217d924d3f19848f48..28c671b609b2f44df627788ede37169180e4e8fb 100644 (file)
@@ -1,9 +1,9 @@
-/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_hwi.c: QLogic Linux FCoE offload driver.
  * This file contains the code that low level functions that interact
  * with 57712 FCoE firmware.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 9ecca8504f60e64084e1e55487602011e7386e30..0002caf687dd027f959e76e3e64cac52b7ded11d 100644 (file)
@@ -1,8 +1,8 @@
-/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_io.c: QLogic Linux FCoE offload driver.
  * IO manager and SCSI IO processing.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,11 +40,8 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
 {
        struct bnx2fc_cmd *io_req = container_of(work, struct bnx2fc_cmd,
                                                 timeout_work.work);
-       struct fc_lport *lport;
-       struct fc_rport_priv *rdata;
        u8 cmd_type = io_req->cmd_type;
        struct bnx2fc_rport *tgt = io_req->tgt;
-       int logo_issued;
        int rc;
 
        BNX2FC_IO_DBG(io_req, "cmd_timeout, cmd_type = %d,"
@@ -80,25 +77,14 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
                                        io_req->refcount.refcount.counter);
                        if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
                                               &io_req->req_flags))) {
-
-                               lport = io_req->port->lport;
-                               rdata = io_req->tgt->rdata;
-                               logo_issued = test_and_set_bit(
-                                               BNX2FC_FLAG_EXPL_LOGO,
-                                               &tgt->flags);
+                               /*
+                                * Cleanup and return original command to
+                                * mid-layer.
+                                */
+                               bnx2fc_initiate_cleanup(io_req);
                                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                                spin_unlock_bh(&tgt->tgt_lock);
 
-                               /* Explicitly logo the target */
-                               if (!logo_issued) {
-                                       BNX2FC_IO_DBG(io_req, "Explicit "
-                                                  "logo - tgt flags = 0x%lx\n",
-                                                  tgt->flags);
-
-                                       mutex_lock(&lport->disc.disc_mutex);
-                                       lport->tt.rport_logoff(rdata);
-                                       mutex_unlock(&lport->disc.disc_mutex);
-                               }
                                return;
                        }
                } else {
@@ -116,28 +102,10 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
                                rc = bnx2fc_initiate_abts(io_req);
                                if (rc == SUCCESS)
                                        goto done;
-                               /*
-                                * Explicitly logo the target if
-                                * abts initiation fails
-                                */
-                               lport = io_req->port->lport;
-                               rdata = io_req->tgt->rdata;
-                               logo_issued = test_and_set_bit(
-                                               BNX2FC_FLAG_EXPL_LOGO,
-                                               &tgt->flags);
+
                                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                                spin_unlock_bh(&tgt->tgt_lock);
 
-                               if (!logo_issued) {
-                                       BNX2FC_IO_DBG(io_req, "Explicit "
-                                                  "logo - tgt flags = 0x%lx\n",
-                                                  tgt->flags);
-
-
-                                       mutex_lock(&lport->disc.disc_mutex);
-                                       lport->tt.rport_logoff(rdata);
-                                       mutex_unlock(&lport->disc.disc_mutex);
-                               }
                                return;
                        } else {
                                BNX2FC_IO_DBG(io_req, "IO already in "
@@ -152,22 +120,9 @@ static void bnx2fc_cmd_timeout(struct work_struct *work)
 
                        if (!test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
                                              &io_req->req_flags)) {
-                               lport = io_req->port->lport;
-                               rdata = io_req->tgt->rdata;
-                               logo_issued = test_and_set_bit(
-                                               BNX2FC_FLAG_EXPL_LOGO,
-                                               &tgt->flags);
                                kref_put(&io_req->refcount, bnx2fc_cmd_release);
                                spin_unlock_bh(&tgt->tgt_lock);
 
-                               /* Explicitly logo the target */
-                               if (!logo_issued) {
-                                       BNX2FC_IO_DBG(io_req, "Explicitly logo"
-                                                  "(els)\n");
-                                       mutex_lock(&lport->disc.disc_mutex);
-                                       lport->tt.rport_logoff(rdata);
-                                       mutex_unlock(&lport->disc.disc_mutex);
-                               }
                                return;
                        }
                } else {
@@ -623,8 +578,12 @@ int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
        mp_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
        memset(mp_req, 0, sizeof(struct bnx2fc_mp_req));
 
-       mp_req->req_len = sizeof(struct fcp_cmnd);
-       io_req->data_xfer_len = mp_req->req_len;
+       if (io_req->cmd_type != BNX2FC_ELS) {
+               mp_req->req_len = sizeof(struct fcp_cmnd);
+               io_req->data_xfer_len = mp_req->req_len;
+       } else
+               mp_req->req_len = io_req->data_xfer_len;
+
        mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, CNIC_PAGE_SIZE,
                                             &mp_req->req_buf_dma,
                                             GFP_ATOMIC);
@@ -1108,18 +1067,11 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
        return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
 }
 
-int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
+int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
 {
        struct bnx2fc_rport *tgt = io_req->tgt;
-       struct fc_rport_priv *rdata = tgt->rdata;
-       int logo_issued;
        int rc = SUCCESS;
-       int wait_cnt = 0;
 
-       BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
-                     tgt->flags);
-       logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
-                                      &tgt->flags);
        io_req->wait_for_comp = 1;
        bnx2fc_initiate_cleanup(io_req);
 
@@ -1132,21 +1084,8 @@ int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
         * release the reference taken in eh_abort to allow the
         * target to re-login after flushing IOs
         */
-        kref_put(&io_req->refcount, bnx2fc_cmd_release);
-
-       if (!logo_issued) {
-               clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
-               mutex_lock(&lport->disc.disc_mutex);
-               lport->tt.rport_logoff(rdata);
-               mutex_unlock(&lport->disc.disc_mutex);
-               do {
-                       msleep(BNX2FC_RELOGIN_WAIT_TIME);
-                       if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) {
-                               rc = FAILED;
-                               break;
-                       }
-               } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags));
-       }
+       kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
        spin_lock_bh(&tgt->tgt_lock);
        return rc;
 }
@@ -1248,7 +1187,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
                if (cancel_delayed_work(&io_req->timeout_work))
                        kref_put(&io_req->refcount,
                                 bnx2fc_cmd_release); /* drop timer hold */
-               rc = bnx2fc_expl_logo(lport, io_req);
+               rc = bnx2fc_abts_cleanup(io_req);
                /* This only occurs when an task abort was requested while ABTS
                   is in progress.  Setting the IO_CLEANUP flag will skip the
                   RRQ process in the case when the fw generated SCSI_CMD cmpl
@@ -1287,7 +1226,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
                /* Let the scsi-ml try to recover this command */
                printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
                       io_req->xid);
-               rc = bnx2fc_expl_logo(lport, io_req);
+               rc = bnx2fc_abts_cleanup(io_req);
                goto out;
        } else {
                /*
@@ -1755,7 +1694,10 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
        int fcp_rsp_len = 0;
 
        io_req->fcp_status = FC_GOOD;
-       io_req->fcp_resid = fcp_rsp->fcp_resid;
+       io_req->fcp_resid = 0;
+       if (rsp_flags & (FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER |
+           FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER))
+               io_req->fcp_resid = fcp_rsp->fcp_resid;
 
        io_req->scsi_comp_flags = rsp_flags;
        CMD_SCSI_STATUS(sc_cmd) = io_req->cdb_status =
index c66c708412a6a34a8d0cf3f281641b4a594707c1..08ec318afb99ccdaf032959b701313234039c484 100644 (file)
@@ -1,9 +1,9 @@
-/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver.
+/* bnx2fc_tgt.c: QLogic Linux FCoE offload driver.
  * Handles operations such as session offload/upload etc, and manages
  * session resources such as connection id and qp resources.
  *
- * Copyright (c) 2008 - 2013 Broadcom Corporation
- * Copyright (c) 2014, QLogic Corporation
+ * Copyright (c) 2008-2013 Broadcom Corporation
+ * Copyright (c) 2014-2015 QLogic Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -560,12 +560,6 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
                    (hba->num_ofld_sess == 0)) {
                        wake_up_interruptible(&hba->shutdown_wait);
                }
-               if (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags)) {
-                       printk(KERN_ERR PFX "Relogin to the tgt\n");
-                       mutex_lock(&lport->disc.disc_mutex);
-                       lport->tt.rport_login(rdata);
-                       mutex_unlock(&lport->disc.disc_mutex);
-               }
                mutex_unlock(&hba->hba_mutex);
 
                break;
index 2c4562d82dc06281dc9e9e51cf1e8a9701c041c1..c2a6f9f294271c5db4f2ec2b885d87b5ec849a4d 100644 (file)
@@ -2283,7 +2283,6 @@ struct scsi_host_template csio_fcoe_shost_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = csio_fcoe_lport_attrs,
        .max_sectors            = CSIO_MAX_SECTOR_SIZE,
-       .use_blk_tags           = 1,
 };
 
 struct scsi_host_template csio_fcoe_shost_vport_template = {
@@ -2303,7 +2302,6 @@ struct scsi_host_template csio_fcoe_shost_vport_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = csio_fcoe_vport_attrs,
        .max_sectors            = CSIO_MAX_SECTOR_SIZE,
-       .use_blk_tags           = 1,
 };
 
 /*
index 31f8966b2e037823857bcae96866e414c5709044..33581ba4386e8014290c6ce7e2931a35d8dc07c0 100644 (file)
@@ -256,7 +256,6 @@ static struct scsi_host_template driver_template = {
        .proc_name                      = ESAS2R_DRVR_NAME,
        .change_queue_depth             = scsi_change_queue_depth,
        .max_sectors                    = 0xFFFF,
-       .use_blk_tags                   = 1,
 };
 
 int sgl_page_size = 512;
index 065b25df741b601f7e51345ce1e56d687a09ee0c..71cb05b1c3ebdd9d3d3631ee2da4a44a72b40731 100644 (file)
@@ -2694,7 +2694,6 @@ struct scsi_host_template scsi_esp_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .max_sectors            = 0xffff,
        .skip_settle_delay      = 1,
-       .use_blk_tags           = 1,
 };
 EXPORT_SYMBOL(scsi_esp_template);
 
index d3eb80c46bbe2224ac9cd82b2e3833f28e7ab297..f4424063b860177c6501f4b8796c384b4fed1884 100644 (file)
@@ -287,7 +287,6 @@ static struct scsi_host_template fcoe_shost_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .sg_tablesize = SG_ALL,
        .max_sectors = 0xffff,
-       .use_blk_tags = 1,
        .track_queue_depth = 1,
 };
 
@@ -1873,7 +1872,6 @@ static int fcoe_percpu_receive_thread(void *arg)
 
        set_user_nice(current, MIN_NICE);
 
-retry:
        while (!kthread_should_stop()) {
 
                spin_lock_bh(&p->fcoe_rx_list.lock);
@@ -1883,7 +1881,7 @@ static int fcoe_percpu_receive_thread(void *arg)
                        set_current_state(TASK_INTERRUPTIBLE);
                        spin_unlock_bh(&p->fcoe_rx_list.lock);
                        schedule();
-                       goto retry;
+                       continue;
                }
 
                spin_unlock_bh(&p->fcoe_rx_list.lock);
index 8a0d4d7b3254d715c32cfcc41bb0fc66dd221221..58ce9020d69c5882eebfa46f3ec685fb7b63fef6 100644 (file)
@@ -118,7 +118,6 @@ static struct scsi_host_template fnic_host_template = {
        .sg_tablesize = FNIC_MAX_SG_DESC_CNT,
        .max_sectors = 0xffff,
        .shost_attrs = fnic_attrs,
-       .use_blk_tags = 1,
        .track_queue_depth = 1,
 };
 
@@ -697,13 +696,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        fnic->fnic_max_tag_id = host->can_queue;
 
-       err = scsi_init_shared_tag_map(host, fnic->fnic_max_tag_id);
-       if (err) {
-               shost_printk(KERN_ERR, fnic->lport->host,
-                         "Unable to alloc shared tag map\n");
-               goto err_out_dev_close;
-       }
-
        host->max_lun = fnic->config.luns_per_tgt;
        host->max_id = FNIC_MAX_FCP_TARGET;
        host->max_cmd_len = FCOE_MAX_CMD_LEN;
index 8bb173e01084efb40b80121cda098651375ed3ce..323982fd00c3ba985dfb59bf04b6eff04f86e9b7 100644 (file)
@@ -217,6 +217,13 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
                error = scsi_mq_setup_tags(shost);
                if (error)
                        goto fail;
+       } else {
+               shost->bqt = blk_init_tags(shost->can_queue,
+                               shost->hostt->tag_alloc_policy);
+               if (!shost->bqt) {
+                       error = -ENOMEM;
+                       goto fail;
+               }
        }
 
        /*
index 40669f8dd0df12af584c581d71a151386d9155e2..6a8f95808ee0f92027796651a6254e6c9382ca5a 100644 (file)
@@ -41,6 +41,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_transport_sas.h>
 #include <scsi/scsi_dbg.h>
 #include <linux/cciss_ioctl.h>
 #include <linux/string.h>
 #include "hpsa_cmd.h"
 #include "hpsa.h"
 
-/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */
-#define HPSA_DRIVER_VERSION "3.4.10-0"
+/*
+ * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.'
+ * with an optional trailing '-' followed by a byte value (0-255).
+ */
+#define HPSA_DRIVER_VERSION "3.4.14-0"
 #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
 #define HPSA "hpsa"
 
@@ -205,6 +209,16 @@ static struct board_type products[] = {
        {0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
+static struct scsi_transport_template *hpsa_sas_transport_template;
+static int hpsa_add_sas_host(struct ctlr_info *h);
+static void hpsa_delete_sas_host(struct ctlr_info *h);
+static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node,
+                       struct hpsa_scsi_dev_t *device);
+static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device);
+static struct hpsa_scsi_dev_t
+       *hpsa_find_device_by_sas_rphy(struct ctlr_info *h,
+               struct sas_rphy *rphy);
+
 #define SCSI_CMD_BUSY ((struct scsi_cmnd *)&hpsa_cmd_busy)
 static const struct scsi_cmnd hpsa_cmd_busy;
 #define SCSI_CMD_IDLE ((struct scsi_cmnd *)&hpsa_cmd_idle)
@@ -230,6 +244,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
        int cmd_type);
 static void hpsa_free_cmd_pool(struct ctlr_info *h);
 #define VPD_PAGE (1 << 8)
+#define HPSA_SIMPLE_ERROR_BITS 0x03
 
 static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
 static void hpsa_scan_start(struct Scsi_Host *);
@@ -243,7 +258,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev);
 static int hpsa_slave_configure(struct scsi_device *sdev);
 static void hpsa_slave_destroy(struct scsi_device *sdev);
 
-static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
+static void hpsa_update_scsi_devices(struct ctlr_info *h);
 static int check_for_unit_attention(struct ctlr_info *h,
        struct CommandList *c);
 static void check_ioctl_unit_attention(struct ctlr_info *h,
@@ -274,7 +289,10 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
 static void hpsa_command_resubmit_worker(struct work_struct *work);
 static u32 lockup_detected(struct ctlr_info *h);
 static int detect_controller_lockup(struct ctlr_info *h);
-static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device);
+static void hpsa_disable_rld_caching(struct ctlr_info *h);
+static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
+       struct ReportExtendedLUNdata *buf, int bufsize);
+static int hpsa_luns_changed(struct ctlr_info *h);
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -606,7 +624,7 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
 }
 
 static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",
-       "1(+0)ADM", "UNKNOWN"
+       "1(+0)ADM", "UNKNOWN", "PHYS DRV"
 };
 #define HPSA_RAID_0    0
 #define HPSA_RAID_4    1
@@ -615,7 +633,13 @@ static const char * const raid_label[] = { "0", "4", "1(+0)", "5", "5+1", "6",
 #define HPSA_RAID_51   4
 #define HPSA_RAID_6    5       /* also used for RAID 60 */
 #define HPSA_RAID_ADM  6       /* also used for RAID 1+0 ADM */
-#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
+#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 2)
+#define PHYSICAL_DRIVE (ARRAY_SIZE(raid_label) - 1)
+
+static inline bool is_logical_device(struct hpsa_scsi_dev_t *device)
+{
+       return !device->physical_device;
+}
 
 static ssize_t raid_level_show(struct device *dev,
             struct device_attribute *attr, char *buf)
@@ -637,7 +661,7 @@ static ssize_t raid_level_show(struct device *dev,
        }
 
        /* Is this even a logical drive? */
-       if (!is_logical_dev_addr_mode(hdev->scsi3addr)) {
+       if (!is_logical_device(hdev)) {
                spin_unlock_irqrestore(&h->lock, flags);
                l = snprintf(buf, PAGE_SIZE, "N/A\n");
                return l;
@@ -726,7 +750,6 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev,
 }
 
 #define MAX_PATHS 8
-#define PATH_STRING_LEN 50
 
 static ssize_t path_info_show(struct device *dev,
             struct device_attribute *attr, char *buf)
@@ -742,9 +765,7 @@ static ssize_t path_info_show(struct device *dev,
        u8 path_map_index = 0;
        char *active;
        unsigned char phys_connector[2];
-       unsigned char path[MAX_PATHS][PATH_STRING_LEN];
 
-       memset(path, 0, MAX_PATHS * PATH_STRING_LEN);
        sdev = to_scsi_device(dev);
        h = sdev_to_hba(sdev);
        spin_lock_irqsave(&h->devlock, flags);
@@ -764,18 +785,19 @@ static ssize_t path_info_show(struct device *dev,
                else
                        continue;
 
-               output_len = snprintf(path[i],
-                               PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ",
+               output_len += scnprintf(buf + output_len,
+                               PAGE_SIZE - output_len,
+                               "[%d:%d:%d:%d] %20.20s ",
                                h->scsi_host->host_no,
                                hdev->bus, hdev->target, hdev->lun,
                                scsi_device_type(hdev->devtype));
 
-               if (is_ext_target(h, hdev) ||
-                       (hdev->devtype == TYPE_RAID) ||
-                       is_logical_dev_addr_mode(hdev->scsi3addr)) {
-                       output_len += snprintf(path[i] + output_len,
-                                               PATH_STRING_LEN, "%s\n",
-                                               active);
+               if (hdev->external ||
+                       hdev->devtype == TYPE_RAID ||
+                       is_logical_device(hdev)) {
+                       output_len += snprintf(buf + output_len,
+                                               PAGE_SIZE - output_len,
+                                               "%s\n", active);
                        continue;
                }
 
@@ -787,36 +809,33 @@ static ssize_t path_info_show(struct device *dev,
                if (phys_connector[1] < '0')
                        phys_connector[1] = '0';
                if (hdev->phys_connector[i] > 0)
-                       output_len += snprintf(path[i] + output_len,
-                               PATH_STRING_LEN,
+                       output_len += snprintf(buf + output_len,
+                               PAGE_SIZE - output_len,
                                "PORT: %.2s ",
                                phys_connector);
-               if (hdev->devtype == TYPE_DISK &&
-                       hdev->expose_state != HPSA_DO_NOT_EXPOSE) {
+               if (hdev->devtype == TYPE_DISK && hdev->expose_device) {
                        if (box == 0 || box == 0xFF) {
-                               output_len += snprintf(path[i] + output_len,
-                                       PATH_STRING_LEN,
+                               output_len += snprintf(buf + output_len,
+                                       PAGE_SIZE - output_len,
                                        "BAY: %hhu %s\n",
                                        bay, active);
                        } else {
-                               output_len += snprintf(path[i] + output_len,
-                                       PATH_STRING_LEN,
+                               output_len += snprintf(buf + output_len,
+                                       PAGE_SIZE - output_len,
                                        "BOX: %hhu BAY: %hhu %s\n",
                                        box, bay, active);
                        }
                } else if (box != 0 && box != 0xFF) {
-                       output_len += snprintf(path[i] + output_len,
-                               PATH_STRING_LEN, "BOX: %hhu %s\n",
+                       output_len += snprintf(buf + output_len,
+                               PAGE_SIZE - output_len, "BOX: %hhu %s\n",
                                box, active);
                } else
-                       output_len += snprintf(path[i] + output_len,
-                               PATH_STRING_LEN, "%s\n", active);
+                       output_len += snprintf(buf + output_len,
+                               PAGE_SIZE - output_len, "%s\n", active);
        }
 
        spin_unlock_irqrestore(&h->devlock, flags);
-       return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s",
-               path[0], path[1], path[2], path[3],
-               path[4], path[5], path[6], path[7]);
+       return output_len;
 }
 
 static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
@@ -848,7 +867,6 @@ static struct device_attribute *hpsa_sdev_attrs[] = {
        &dev_attr_unique_id,
        &dev_attr_hp_ssd_smart_path_enabled,
        &dev_attr_path_info,
-       &dev_attr_lockup_detected,
        NULL,
 };
 
@@ -860,6 +878,7 @@ static struct device_attribute *hpsa_shost_attrs[] = {
        &dev_attr_resettable,
        &dev_attr_hp_ssd_smart_path_status,
        &dev_attr_raid_offload_debug,
+       &dev_attr_lockup_detected,
        NULL,
 };
 
@@ -1134,25 +1153,62 @@ static int hpsa_find_target_lun(struct ctlr_info *h,
        return !found;
 }
 
-static inline void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
+static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
        struct hpsa_scsi_dev_t *dev, char *description)
 {
+#define LABEL_SIZE 25
+       char label[LABEL_SIZE];
+
+       if (h == NULL || h->pdev == NULL || h->scsi_host == NULL)
+               return;
+
+       switch (dev->devtype) {
+       case TYPE_RAID:
+               snprintf(label, LABEL_SIZE, "controller");
+               break;
+       case TYPE_ENCLOSURE:
+               snprintf(label, LABEL_SIZE, "enclosure");
+               break;
+       case TYPE_DISK:
+               if (dev->external)
+                       snprintf(label, LABEL_SIZE, "external");
+               else if (!is_logical_dev_addr_mode(dev->scsi3addr))
+                       snprintf(label, LABEL_SIZE, "%s",
+                               raid_label[PHYSICAL_DRIVE]);
+               else
+                       snprintf(label, LABEL_SIZE, "RAID-%s",
+                               dev->raid_level > RAID_UNKNOWN ? "?" :
+                               raid_label[dev->raid_level]);
+               break;
+       case TYPE_ROM:
+               snprintf(label, LABEL_SIZE, "rom");
+               break;
+       case TYPE_TAPE:
+               snprintf(label, LABEL_SIZE, "tape");
+               break;
+       case TYPE_MEDIUM_CHANGER:
+               snprintf(label, LABEL_SIZE, "changer");
+               break;
+       default:
+               snprintf(label, LABEL_SIZE, "UNKNOWN");
+               break;
+       }
+
        dev_printk(level, &h->pdev->dev,
-                       "scsi %d:%d:%d:%d: %s %s %.8s %.16s RAID-%s SSDSmartPathCap%c En%c Exp=%d\n",
+                       "scsi %d:%d:%d:%d: %s %s %.8s %.16s %s SSDSmartPathCap%c En%c Exp=%d\n",
                        h->scsi_host->host_no, dev->bus, dev->target, dev->lun,
                        description,
                        scsi_device_type(dev->devtype),
                        dev->vendor,
                        dev->model,
-                       dev->raid_level > RAID_UNKNOWN ?
-                               "RAID-?" : raid_label[dev->raid_level],
+                       label,
                        dev->offload_config ? '+' : '-',
                        dev->offload_enabled ? '+' : '-',
-                       dev->expose_state);
+                       dev->expose_device);
 }
 
 /* Add an entry into h->dev[] array. */
-static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
+static int hpsa_scsi_add_entry(struct ctlr_info *h,
                struct hpsa_scsi_dev_t *device,
                struct hpsa_scsi_dev_t *added[], int *nadded)
 {
@@ -1221,14 +1277,14 @@ static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
        added[*nadded] = device;
        (*nadded)++;
        hpsa_show_dev_msg(KERN_INFO, h, device,
-               device->expose_state & HPSA_SCSI_ADD ? "added" : "masked");
+               device->expose_device ? "added" : "masked");
        device->offload_to_be_enabled = device->offload_enabled;
        device->offload_enabled = 0;
        return 0;
 }
 
 /* Update an entry in h->dev[] array. */
-static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
+static void hpsa_scsi_update_entry(struct ctlr_info *h,
        int entry, struct hpsa_scsi_dev_t *new_entry)
 {
        int offload_enabled;
@@ -1276,7 +1332,7 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, int hostno,
 }
 
 /* Replace an entry from h->dev[] array. */
-static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
+static void hpsa_scsi_replace_entry(struct ctlr_info *h,
        int entry, struct hpsa_scsi_dev_t *new_entry,
        struct hpsa_scsi_dev_t *added[], int *nadded,
        struct hpsa_scsi_dev_t *removed[], int *nremoved)
@@ -1304,7 +1360,7 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
 }
 
 /* Remove an entry from h->dev[] array. */
-static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
+static void hpsa_scsi_remove_entry(struct ctlr_info *h, int entry,
        struct hpsa_scsi_dev_t *removed[], int *nremoved)
 {
        /* assumes h->devlock is held */
@@ -1415,6 +1471,9 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
 #define DEVICE_CHANGED 1
 #define DEVICE_SAME 2
 #define DEVICE_UPDATED 3
+       if (needle == NULL)
+               return DEVICE_NOT_FOUND;
+
        for (i = 0; i < haystack_size; i++) {
                if (haystack[i] == NULL) /* previously removed. */
                        continue;
@@ -1577,9 +1636,11 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
                if (!logical_drive->offload_config)
                        continue;
                for (j = 0; j < ndevices; j++) {
+                       if (dev[j] == NULL)
+                               continue;
                        if (dev[j]->devtype != TYPE_DISK)
                                continue;
-                       if (is_logical_dev_addr_mode(dev[j]->scsi3addr))
+                       if (is_logical_device(dev[j]))
                                continue;
                        if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle)
                                continue;
@@ -1620,9 +1681,11 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
        int i;
 
        for (i = 0; i < ndevices; i++) {
+               if (dev[i] == NULL)
+                       continue;
                if (dev[i]->devtype != TYPE_DISK)
                        continue;
-               if (!is_logical_dev_addr_mode(dev[i]->scsi3addr))
+               if (!is_logical_device(dev[i]))
                        continue;
 
                /*
@@ -1638,7 +1701,50 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
        }
 }
 
-static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
+static int hpsa_add_device(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
+{
+       int rc = 0;
+
+       if (!h->scsi_host)
+               return 1;
+
+       if (is_logical_device(device)) /* RAID */
+               rc = scsi_add_device(h->scsi_host, device->bus,
+                                       device->target, device->lun);
+       else /* HBA */
+               rc = hpsa_add_sas_device(h->sas_host, device);
+
+       return rc;
+}
+
+static void hpsa_remove_device(struct ctlr_info *h,
+                       struct hpsa_scsi_dev_t *device)
+{
+       struct scsi_device *sdev = NULL;
+
+       if (!h->scsi_host)
+               return;
+
+       if (is_logical_device(device)) { /* RAID */
+               sdev = scsi_device_lookup(h->scsi_host, device->bus,
+                                               device->target, device->lun);
+               if (sdev) {
+                       scsi_remove_device(sdev);
+                       scsi_device_put(sdev);
+               } else {
+                       /*
+                        * We don't expect to get here.  Future commands
+                        * to this device will get a selection timeout as
+                        * if the device were gone.
+                        */
+                       hpsa_show_dev_msg(KERN_WARNING, h, device,
+                                       "didn't find device for removal.");
+               }
+       } else /* HBA */
+               hpsa_remove_sas_device(device);
+}
+
+static void adjust_hpsa_scsi_table(struct ctlr_info *h,
        struct hpsa_scsi_dev_t *sd[], int nsds)
 {
        /* sd contains scsi3 addresses and devtypes, and inquiry
@@ -1650,7 +1756,15 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
        unsigned long flags;
        struct hpsa_scsi_dev_t **added, **removed;
        int nadded, nremoved;
-       struct Scsi_Host *sh = NULL;
+
+       /*
+        * A reset can cause a device status to change
+        * re-schedule the scan to see what happened.
+        */
+       if (h->reset_in_progress) {
+               h->drv_req_rescan = 1;
+               return;
+       }
 
        added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL);
        removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL);
@@ -1678,19 +1792,18 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
                device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry);
                if (device_change == DEVICE_NOT_FOUND) {
                        changes++;
-                       hpsa_scsi_remove_entry(h, hostno, i,
-                               removed, &nremoved);
+                       hpsa_scsi_remove_entry(h, i, removed, &nremoved);
                        continue; /* remove ^^^, hence i not incremented */
                } else if (device_change == DEVICE_CHANGED) {
                        changes++;
-                       hpsa_scsi_replace_entry(h, hostno, i, sd[entry],
+                       hpsa_scsi_replace_entry(h, i, sd[entry],
                                added, &nadded, removed, &nremoved);
                        /* Set it to NULL to prevent it from being freed
                         * at the bottom of hpsa_update_scsi_devices()
                         */
                        sd[entry] = NULL;
                } else if (device_change == DEVICE_UPDATED) {
-                       hpsa_scsi_update_entry(h, hostno, i, sd[entry]);
+                       hpsa_scsi_update_entry(h, i, sd[entry]);
                }
                i++;
        }
@@ -1718,8 +1831,7 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
                                        h->ndevices, &entry);
                if (device_change == DEVICE_NOT_FOUND) {
                        changes++;
-                       if (hpsa_scsi_add_entry(h, hostno, sd[i],
-                               added, &nadded) != 0)
+                       if (hpsa_scsi_add_entry(h, sd[i], added, &nadded) != 0)
                                break;
                        sd[i] = NULL; /* prevent from being freed later. */
                } else if (device_change == DEVICE_CHANGED) {
@@ -1735,8 +1847,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
        /* Now that h->dev[]->phys_disk[] is coherent, we can enable
         * any logical drives that need it enabled.
         */
-       for (i = 0; i < h->ndevices; i++)
+       for (i = 0; i < h->ndevices; i++) {
+               if (h->dev[i] == NULL)
+                       continue;
                h->dev[i]->offload_enabled = h->dev[i]->offload_to_be_enabled;
+       }
 
        spin_unlock_irqrestore(&h->devlock, flags);
 
@@ -1755,47 +1870,37 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
         * (or if there are no changes) scsi_scan_host will do it later the
         * first time through.
         */
-       if (hostno == -1 || !changes)
+       if (!changes)
                goto free_and_out;
 
-       sh = h->scsi_host;
        /* Notify scsi mid layer of any removed devices */
        for (i = 0; i < nremoved; i++) {
-               if (removed[i]->expose_state & HPSA_SCSI_ADD) {
-                       struct scsi_device *sdev =
-                               scsi_device_lookup(sh, removed[i]->bus,
-                                       removed[i]->target, removed[i]->lun);
-                       if (sdev != NULL) {
-                               scsi_remove_device(sdev);
-                               scsi_device_put(sdev);
-                       } else {
-                               /*
-                                * We don't expect to get here.
-                                * future cmds to this device will get selection
-                                * timeout as if the device was gone.
-                                */
-                               hpsa_show_dev_msg(KERN_WARNING, h, removed[i],
-                                       "didn't find device for removal.");
-                       }
-               }
+               if (removed[i] == NULL)
+                       continue;
+               if (removed[i]->expose_device)
+                       hpsa_remove_device(h, removed[i]);
                kfree(removed[i]);
                removed[i] = NULL;
        }
 
        /* Notify scsi mid layer of any added devices */
        for (i = 0; i < nadded; i++) {
-               if (!(added[i]->expose_state & HPSA_SCSI_ADD))
+               int rc = 0;
+
+               if (added[i] == NULL)
+                       continue;
+               if (!(added[i]->expose_device))
                        continue;
-               if (scsi_add_device(sh, added[i]->bus,
-                       added[i]->target, added[i]->lun) == 0)
+               rc = hpsa_add_device(h, added[i]);
+               if (!rc)
                        continue;
-               hpsa_show_dev_msg(KERN_WARNING, h, added[i],
-                                       "addition failed, device not added.");
+               dev_warn(&h->pdev->dev,
+                       "addition failed %d, device not added.", rc);
                /* now we have to remove it from h->dev,
                 * since it didn't get added to scsi mid layer
                 */
                fixup_botched_add(h, added[i]);
-               added[i] = NULL;
+               h->drv_req_rescan = 1;
        }
 
 free_and_out:
@@ -1829,11 +1934,24 @@ static int hpsa_slave_alloc(struct scsi_device *sdev)
 
        h = sdev_to_hba(sdev);
        spin_lock_irqsave(&h->devlock, flags);
-       sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
-               sdev_id(sdev), sdev->lun);
-       if (likely(sd)) {
+       if (sdev_channel(sdev) == HPSA_PHYSICAL_DEVICE_BUS) {
+               struct scsi_target *starget;
+               struct sas_rphy *rphy;
+
+               starget = scsi_target(sdev);
+               rphy = target_to_rphy(starget);
+               sd = hpsa_find_device_by_sas_rphy(h, rphy);
+               if (sd) {
+                       sd->target = sdev_id(sdev);
+                       sd->lun = sdev->lun;
+               }
+       } else
+               sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
+                                       sdev_id(sdev), sdev->lun);
+
+       if (sd && sd->expose_device) {
                atomic_set(&sd->ioaccel_cmds_out, 0);
-               sdev->hostdata = (sd->expose_state & HPSA_SCSI_ADD) ? sd : NULL;
+               sdev->hostdata = sd;
        } else
                sdev->hostdata = NULL;
        spin_unlock_irqrestore(&h->devlock, flags);
@@ -1847,7 +1965,7 @@ static int hpsa_slave_configure(struct scsi_device *sdev)
        int queue_depth;
 
        sd = sdev->hostdata;
-       sdev->no_uld_attach = !sd || !(sd->expose_state & HPSA_ULD_ATTACH);
+       sdev->no_uld_attach = !sd || !sd->expose_device;
 
        if (sd)
                queue_depth = sd->queue_depth != 0 ?
@@ -1955,7 +2073,7 @@ static int hpsa_map_ioaccel2_sg_chain_block(struct ctlr_info *h,
        u32 chain_size;
 
        chain_block = h->ioaccel2_cmd_sg_list[c->cmdindex];
-       chain_size = le32_to_cpu(cp->data_len);
+       chain_size = le32_to_cpu(cp->sg[0].length);
        temp64 = pci_map_single(h->pdev, chain_block, chain_size,
                                PCI_DMA_TODEVICE);
        if (dma_mapping_error(&h->pdev->dev, temp64)) {
@@ -1976,7 +2094,7 @@ static void hpsa_unmap_ioaccel2_sg_chain_block(struct ctlr_info *h,
 
        chain_sg = cp->sg;
        temp64 = le64_to_cpu(chain_sg->address);
-       chain_size = le32_to_cpu(cp->data_len);
+       chain_size = le32_to_cpu(cp->sg[0].length);
        pci_unmap_single(h->pdev, temp64, chain_size, PCI_DMA_TODEVICE);
 }
 
@@ -2210,7 +2328,7 @@ static void process_ioaccel2_completion(struct ctlr_info *h,
         * the normal I/O path so the controller can handle whatever's
         * wrong.
         */
-       if (is_logical_dev_addr_mode(dev->scsi3addr) &&
+       if (is_logical_device(dev) &&
                c2->error_data.serv_response ==
                        IOACCEL2_SERV_RESPONSE_FAILURE) {
                if (c2->error_data.status ==
@@ -2330,7 +2448,7 @@ static void complete_scsi_command(struct CommandList *cp)
                 * the normal I/O path so the controller can handle whatever's
                 * wrong.
                 */
-               if (is_logical_dev_addr_mode(dev->scsi3addr)) {
+               if (is_logical_device(dev)) {
                        if (ei->CommandStatus == CMD_IOACCEL_DISABLED)
                                dev->offload_enabled = 0;
                        return hpsa_retry_cmd(h, cp);
@@ -2709,9 +2827,8 @@ static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr,
 
 
        /* fill_cmd can't fail here, no data buffer to map. */
-       (void) fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0,
+       (void) fill_cmd(c, reset_type, h, NULL, 0, 0,
                        scsi3addr, TYPE_MSG);
-       c->Request.CDB[1] = reset_type; /* fill_cmd defaults to LUN reset */
        rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT);
        if (rc) {
                dev_warn(&h->pdev->dev, "Failed to send reset command\n");
@@ -2984,6 +3101,66 @@ static int hpsa_get_raid_map(struct ctlr_info *h,
        return rc;
 }
 
+static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h,
+               unsigned char scsi3addr[], u16 bmic_device_index,
+               struct bmic_sense_subsystem_info *buf, size_t bufsize)
+{
+       int rc = IO_OK;
+       struct CommandList *c;
+       struct ErrorInfo *ei;
+
+       c = cmd_alloc(h);
+
+       rc = fill_cmd(c, BMIC_SENSE_SUBSYSTEM_INFORMATION, h, buf, bufsize,
+               0, RAID_CTLR_LUNID, TYPE_CMD);
+       if (rc)
+               goto out;
+
+       c->Request.CDB[2] = bmic_device_index & 0xff;
+       c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff;
+
+       rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+                               PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+       if (rc)
+               goto out;
+       ei = c->err_info;
+       if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+               hpsa_scsi_interpret_error(h, c);
+               rc = -1;
+       }
+out:
+       cmd_free(h, c);
+       return rc;
+}
+
+static int hpsa_bmic_id_controller(struct ctlr_info *h,
+       struct bmic_identify_controller *buf, size_t bufsize)
+{
+       int rc = IO_OK;
+       struct CommandList *c;
+       struct ErrorInfo *ei;
+
+       c = cmd_alloc(h);
+
+       rc = fill_cmd(c, BMIC_IDENTIFY_CONTROLLER, h, buf, bufsize,
+               0, RAID_CTLR_LUNID, TYPE_CMD);
+       if (rc)
+               goto out;
+
+       rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+               PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+       if (rc)
+               goto out;
+       ei = c->err_info;
+       if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+               hpsa_scsi_interpret_error(h, c);
+               rc = -1;
+       }
+out:
+       cmd_free(h, c);
+       return rc;
+}
+
 static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
                unsigned char scsi3addr[], u16 bmic_device_index,
                struct bmic_identify_physical_device *buf, size_t bufsize)
@@ -3010,9 +3187,71 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h,
        }
 out:
        cmd_free(h, c);
+
        return rc;
 }
 
+static u64 hpsa_get_sas_address_from_report_physical(struct ctlr_info *h,
+                                               unsigned char *scsi3addr)
+{
+       struct ReportExtendedLUNdata *physdev;
+       u32 nphysicals;
+       u64 sa = 0;
+       int i;
+
+       physdev = kzalloc(sizeof(*physdev), GFP_KERNEL);
+       if (!physdev)
+               return 0;
+
+       if (hpsa_scsi_do_report_phys_luns(h, physdev, sizeof(*physdev))) {
+               dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
+               kfree(physdev);
+               return 0;
+       }
+       nphysicals = get_unaligned_be32(physdev->LUNListLength) / 24;
+
+       for (i = 0; i < nphysicals; i++)
+               if (!memcmp(&physdev->LUN[i].lunid[0], scsi3addr, 8)) {
+                       sa = get_unaligned_be64(&physdev->LUN[i].wwid[0]);
+                       break;
+               }
+
+       kfree(physdev);
+
+       return sa;
+}
+
+static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr,
+                                       struct hpsa_scsi_dev_t *dev)
+{
+       int rc;
+       u64 sa = 0;
+
+       if (is_hba_lunid(scsi3addr)) {
+               struct bmic_sense_subsystem_info *ssi;
+
+               ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
+               if (ssi == NULL) {
+                       dev_warn(&h->pdev->dev,
+                               "%s: out of memory\n", __func__);
+                       return;
+               }
+
+               rc = hpsa_bmic_sense_subsystem_information(h,
+                                       scsi3addr, 0, ssi, sizeof(*ssi));
+               if (rc == 0) {
+                       sa = get_unaligned_be64(ssi->primary_world_wide_id);
+                       h->sas_address = sa;
+               }
+
+               kfree(ssi);
+       } else
+               sa = hpsa_get_sas_address_from_report_physical(h, scsi3addr);
+
+       dev->sas_address = sa;
+}
+
+/* Get a device id from inquiry page 0x83 */
 static int hpsa_vpd_page_supported(struct ctlr_info *h,
        unsigned char scsi3addr[], u8 page)
 {
@@ -3097,7 +3336,7 @@ static void hpsa_get_ioaccel_status(struct ctlr_info *h,
 
 /* Get the device id from inquiry page 0x83 */
 static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
-       unsigned char *device_id, int buflen)
+       unsigned char *device_id, int index, int buflen)
 {
        int rc;
        unsigned char *buf;
@@ -3109,8 +3348,10 @@ static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
                return -ENOMEM;
        rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64);
        if (rc == 0)
-               memcpy(device_id, &buf[8], buflen);
+               memcpy(device_id, &buf[index], buflen);
+
        kfree(buf);
+
        return rc != 0;
 }
 
@@ -3339,6 +3580,18 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h,
        return rc;
 }
 
+static void sanitize_inquiry_string(unsigned char *s, int len)
+{
+       bool terminated = false;
+
+       for (; len > 0; (--len, ++s)) {
+               if (*s == 0)
+                       terminated = true;
+               if (terminated || *s < 0x20 || *s > 0x7e)
+                       *s = ' ';
+       }
+}
+
 static int hpsa_update_device_info(struct ctlr_info *h,
        unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
        unsigned char *is_OBDR_device)
@@ -3351,10 +3604,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,
 
        unsigned char *inq_buff;
        unsigned char *obdr_sig;
+       int rc = 0;
 
        inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
-       if (!inq_buff)
+       if (!inq_buff) {
+               rc = -ENOMEM;
                goto bail_out;
+       }
 
        /* Do an inquiry to the device to see what it is. */
        if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
@@ -3362,9 +3618,13 @@ static int hpsa_update_device_info(struct ctlr_info *h,
                /* Inquiry failed (msg printed already) */
                dev_err(&h->pdev->dev,
                        "hpsa_update_device_info: inquiry failed\n");
+               rc = -EIO;
                goto bail_out;
        }
 
+       sanitize_inquiry_string(&inq_buff[8], 8);
+       sanitize_inquiry_string(&inq_buff[16], 16);
+
        this_device->devtype = (inq_buff[0] & 0x1f);
        memcpy(this_device->scsi3addr, scsi3addr, 8);
        memcpy(this_device->vendor, &inq_buff[8],
@@ -3373,7 +3633,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
                sizeof(this_device->model));
        memset(this_device->device_id, 0,
                sizeof(this_device->device_id));
-       hpsa_get_device_id(h, scsi3addr, this_device->device_id,
+       hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
                sizeof(this_device->device_id));
 
        if (this_device->devtype == TYPE_DISK &&
@@ -3411,7 +3671,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
 
 bail_out:
        kfree(inq_buff);
-       return 1;
+       return rc;
 }
 
 static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
@@ -3439,115 +3699,39 @@ static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
        }
 }
 
-static unsigned char *ext_target_model[] = {
-       "MSA2012",
-       "MSA2024",
-       "MSA2312",
-       "MSA2324",
-       "P2000 G3 SAS",
-       "MSA 2040 SAS",
-       NULL,
-};
-
-static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
-{
-       int i;
-
-       for (i = 0; ext_target_model[i]; i++)
-               if (strncmp(device->model, ext_target_model[i],
-                       strlen(ext_target_model[i])) == 0)
-                       return 1;
-       return 0;
-}
-
-/* Helper function to assign bus, target, lun mapping of devices.
- * Puts non-external target logical volumes on bus 0, external target logical
- * volumes on bus 1, physical devices on bus 2. and the hba on bus 3.
+/*
+ * Helper function to assign bus, target, lun mapping of devices.
  * Logical drive target and lun are assigned at this time, but
  * physical device lun and target assignment are deferred (assigned
  * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
- */
+*/
 static void figure_bus_target_lun(struct ctlr_info *h,
        u8 *lunaddrbytes, struct hpsa_scsi_dev_t *device)
 {
-       u32 lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
+       u32 lunid = get_unaligned_le32(lunaddrbytes);
 
        if (!is_logical_dev_addr_mode(lunaddrbytes)) {
                /* physical device, target and lun filled in later */
                if (is_hba_lunid(lunaddrbytes))
-                       hpsa_set_bus_target_lun(device, 3, 0, lunid & 0x3fff);
+                       hpsa_set_bus_target_lun(device,
+                                       HPSA_HBA_BUS, 0, lunid & 0x3fff);
                else
                        /* defer target, lun assignment for physical devices */
-                       hpsa_set_bus_target_lun(device, 2, -1, -1);
+                       hpsa_set_bus_target_lun(device,
+                                       HPSA_PHYSICAL_DEVICE_BUS, -1, -1);
                return;
        }
        /* It's a logical device */
-       if (is_ext_target(h, device)) {
-               /* external target way, put logicals on bus 1
-                * and match target/lun numbers box
-                * reports, other smart array, bus 0, target 0, match lunid
-                */
+       if (device->external) {
                hpsa_set_bus_target_lun(device,
-                       1, (lunid >> 16) & 0x3fff, lunid & 0x00ff);
+                       HPSA_EXTERNAL_RAID_VOLUME_BUS, (lunid >> 16) & 0x3fff,
+                       lunid & 0x00ff);
                return;
        }
-       hpsa_set_bus_target_lun(device, 0, 0, lunid & 0x3fff);
+       hpsa_set_bus_target_lun(device, HPSA_RAID_VOLUME_BUS,
+                               0, lunid & 0x3fff);
 }
 
-/*
- * If there is no lun 0 on a target, linux won't find any devices.
- * For the external targets (arrays), we have to manually detect the enclosure
- * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report
- * it for some reason.  *tmpdevice is the target we're adding,
- * this_device is a pointer into the current element of currentsd[]
- * that we're building up in update_scsi_devices(), below.
- * lunzerobits is a bitmap that tracks which targets already have a
- * lun 0 assigned.
- * Returns 1 if an enclosure was added, 0 if not.
- */
-static int add_ext_target_dev(struct ctlr_info *h,
-       struct hpsa_scsi_dev_t *tmpdevice,
-       struct hpsa_scsi_dev_t *this_device, u8 *lunaddrbytes,
-       unsigned long lunzerobits[], int *n_ext_target_devs)
-{
-       unsigned char scsi3addr[8];
-
-       if (test_bit(tmpdevice->target, lunzerobits))
-               return 0; /* There is already a lun 0 on this target. */
-
-       if (!is_logical_dev_addr_mode(lunaddrbytes))
-               return 0; /* It's the logical targets that may lack lun 0. */
-
-       if (!is_ext_target(h, tmpdevice))
-               return 0; /* Only external target devices have this problem. */
-
-       if (tmpdevice->lun == 0) /* if lun is 0, then we have a lun 0. */
-               return 0;
-
-       memset(scsi3addr, 0, 8);
-       scsi3addr[3] = tmpdevice->target;
-       if (is_hba_lunid(scsi3addr))
-               return 0; /* Don't add the RAID controller here. */
-
-       if (is_scsi_rev_5(h))
-               return 0; /* p1210m doesn't need to do this. */
-
-       if (*n_ext_target_devs >= MAX_EXT_TARGETS) {
-               dev_warn(&h->pdev->dev, "Maximum number of external "
-                       "target devices exceeded.  Check your hardware "
-                       "configuration.");
-               return 0;
-       }
-
-       if (hpsa_update_device_info(h, scsi3addr, this_device, NULL))
-               return 0;
-       (*n_ext_target_devs)++;
-       hpsa_set_bus_target_lun(this_device,
-                               tmpdevice->bus, tmpdevice->target, 0);
-       hpsa_update_device_supports_aborts(h, this_device, scsi3addr);
-       set_bit(tmpdevice->target, lunzerobits);
-       return 1;
-}
 
 /*
  * Get address of physical disk used for an ioaccel2 mode command:
@@ -3577,6 +3761,27 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
        return 0;
 }
 
+static int  figure_external_status(struct ctlr_info *h, int raid_ctlr_position,
+       int i, int nphysicals, int nlocal_logicals)
+{
+       /* In report logicals, local logicals are listed first,
+       * then any externals.
+       */
+       int logicals_start = nphysicals + (raid_ctlr_position == 0);
+
+       if (i == raid_ctlr_position)
+               return 0;
+
+       if (i < logicals_start)
+               return 0;
+
+       /* i is in logicals range, but still within local logicals */
+       if ((i - nphysicals - (raid_ctlr_position == 0)) < nlocal_logicals)
+               return 0;
+
+       return 1; /* it's an external lun */
+}
+
 /*
  * Do CISS_REPORT_PHYS and CISS_REPORT_LOG.  Data is returned in physdev,
  * logdev.  The number of luns in physdev and logdev are returned in
@@ -3650,19 +3855,18 @@ static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position,
 /* get physical drive ioaccel handle and queue depth */
 static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
                struct hpsa_scsi_dev_t *dev,
-               u8 *lunaddrbytes,
+               struct ReportExtendedLUNdata *rlep, int rle_index,
                struct bmic_identify_physical_device *id_phys)
 {
        int rc;
-       struct ext_report_lun_entry *rle =
-               (struct ext_report_lun_entry *) lunaddrbytes;
+       struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
 
        dev->ioaccel_handle = rle->ioaccel_handle;
-       if (PHYS_IOACCEL(lunaddrbytes) && dev->ioaccel_handle)
+       if ((rle->device_flags & 0x08) && dev->ioaccel_handle)
                dev->hba_ioaccel_enabled = 1;
        memset(id_phys, 0, sizeof(*id_phys));
-       rc = hpsa_bmic_id_physical_device(h, lunaddrbytes,
-                       GET_BMIC_DRIVE_NUMBER(lunaddrbytes), id_phys,
+       rc = hpsa_bmic_id_physical_device(h, &rle->lunid[0],
+                       GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]), id_phys,
                        sizeof(*id_phys));
        if (!rc)
                /* Reserve space for FW operations */
@@ -3673,16 +3877,15 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
                                DRIVE_CMDS_RESERVED_FOR_FW;
        else
                dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */
-       atomic_set(&dev->ioaccel_cmds_out, 0);
-       atomic_set(&dev->reset_cmds_out, 0);
 }
 
 static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device,
-       u8 *lunaddrbytes,
+       struct ReportExtendedLUNdata *rlep, int rle_index,
        struct bmic_identify_physical_device *id_phys)
 {
-       if (PHYS_IOACCEL(lunaddrbytes)
-               && this_device->ioaccel_handle)
+       struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
+
+       if ((rle->device_flags & 0x08) && this_device->ioaccel_handle)
                this_device->hba_ioaccel_enabled = 1;
 
        memcpy(&this_device->active_path_index,
@@ -3702,7 +3905,33 @@ static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device,
                sizeof(this_device->bay));
 }
 
-static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
+/* get number of local logical disks. */
+static int hpsa_set_local_logical_count(struct ctlr_info *h,
+       struct bmic_identify_controller *id_ctlr,
+       u32 *nlocals)
+{
+       int rc;
+
+       if (!id_ctlr) {
+               dev_warn(&h->pdev->dev, "%s: id_ctlr buffer is NULL.\n",
+                       __func__);
+               return -ENOMEM;
+       }
+       memset(id_ctlr, 0, sizeof(*id_ctlr));
+       rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr));
+       if (!rc)
+               if (id_ctlr->configured_logical_drive_count < 256)
+                       *nlocals = id_ctlr->configured_logical_drive_count;
+               else
+                       *nlocals = le16_to_cpu(
+                                       id_ctlr->extended_logical_unit_count);
+       else
+               *nlocals = -1;
+       return rc;
+}
+
+
+static void hpsa_update_scsi_devices(struct ctlr_info *h)
 {
        /* the idea here is we could get notified
         * that some devices have changed, so we do a report
@@ -3717,13 +3946,16 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        struct ReportExtendedLUNdata *physdev_list = NULL;
        struct ReportLUNdata *logdev_list = NULL;
        struct bmic_identify_physical_device *id_phys = NULL;
+       struct bmic_identify_controller *id_ctlr = NULL;
        u32 nphysicals = 0;
        u32 nlogicals = 0;
+       u32 nlocal_logicals = 0;
        u32 ndev_allocated = 0;
        struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
        int ncurrent = 0;
        int i, n_ext_target_devs, ndevs_to_allocate;
        int raid_ctlr_position;
+       bool physical_device;
        DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
 
        currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
@@ -3731,17 +3963,29 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
        tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
        id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL);
+       id_ctlr = kzalloc(sizeof(*id_ctlr), GFP_KERNEL);
 
        if (!currentsd || !physdev_list || !logdev_list ||
-               !tmpdevice || !id_phys) {
+               !tmpdevice || !id_phys || !id_ctlr) {
                dev_err(&h->pdev->dev, "out of memory\n");
                goto out;
        }
        memset(lunzerobits, 0, sizeof(lunzerobits));
 
+       h->drv_req_rescan = 0; /* cancel scheduled rescan - we're doing it. */
+
        if (hpsa_gather_lun_info(h, physdev_list, &nphysicals,
-                       logdev_list, &nlogicals))
+                       logdev_list, &nlogicals)) {
+               h->drv_req_rescan = 1;
                goto out;
+       }
+
+       /* Set number of local logicals (non PTRAID) */
+       if (hpsa_set_local_logical_count(h, id_ctlr, &nlocal_logicals)) {
+               dev_warn(&h->pdev->dev,
+                       "%s: Can't determine number of local logical devices.\n",
+                       __func__);
+       }
 
        /* We might see up to the maximum number of logical and physical disks
         * plus external target devices, and a device for the local RAID
@@ -3762,6 +4006,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                if (!currentsd[i]) {
                        dev_warn(&h->pdev->dev, "out of memory at %s:%d\n",
                                __FILE__, __LINE__);
+                       h->drv_req_rescan = 1;
                        goto out;
                }
                ndev_allocated++;
@@ -3776,49 +4021,74 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        n_ext_target_devs = 0;
        for (i = 0; i < nphysicals + nlogicals + 1; i++) {
                u8 *lunaddrbytes, is_OBDR = 0;
+               int rc = 0;
+               int phys_dev_index = i - (raid_ctlr_position == 0);
+
+               physical_device = i < nphysicals + (raid_ctlr_position == 0);
 
                /* Figure out where the LUN ID info is coming from */
                lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
                        i, nphysicals, nlogicals, physdev_list, logdev_list);
 
                /* skip masked non-disk devices */
-               if (MASKED_DEVICE(lunaddrbytes))
-                       if (i < nphysicals + (raid_ctlr_position == 0) &&
-                               NON_DISK_PHYS_DEV(lunaddrbytes))
-                               continue;
+               if (MASKED_DEVICE(lunaddrbytes) && physical_device &&
+                       (physdev_list->LUN[phys_dev_index].device_flags & 0x01))
+                       continue;
 
                /* Get device type, vendor, model, device id */
-               if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
-                                                       &is_OBDR))
-                       continue; /* skip it if we can't talk to it. */
+               rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
+                                                       &is_OBDR);
+               if (rc == -ENOMEM) {
+                       dev_warn(&h->pdev->dev,
+                               "Out of memory, rescan deferred.\n");
+                       h->drv_req_rescan = 1;
+                       goto out;
+               }
+               if (rc) {
+                       dev_warn(&h->pdev->dev,
+                               "Inquiry failed, skipping device.\n");
+                       continue;
+               }
+
+               /* Determine if this is a lun from an external target array */
+               tmpdevice->external =
+                       figure_external_status(h, raid_ctlr_position, i,
+                                               nphysicals, nlocal_logicals);
+
                figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
                hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes);
                this_device = currentsd[ncurrent];
 
-               /*
-                * For external target devices, we have to insert a LUN 0 which
-                * doesn't show up in CCISS_REPORT_PHYSICAL data, but there
-                * is nonetheless an enclosure device there.  We have to
-                * present that otherwise linux won't find anything if
-                * there is no lun 0.
+               /* Turn on discovery_polling if there are ext target devices.
+                * Event-based change notification is unreliable for those.
                 */
-               if (add_ext_target_dev(h, tmpdevice, this_device,
-                               lunaddrbytes, lunzerobits,
-                               &n_ext_target_devs)) {
-                       ncurrent++;
-                       this_device = currentsd[ncurrent];
+               if (!h->discovery_polling) {
+                       if (tmpdevice->external) {
+                               h->discovery_polling = 1;
+                               dev_info(&h->pdev->dev,
+                                       "External target, activate discovery polling.\n");
+                       }
                }
 
+
                *this_device = *tmpdevice;
+               this_device->physical_device = physical_device;
 
-               /* do not expose masked devices */
-               if (MASKED_DEVICE(lunaddrbytes) &&
-                       i < nphysicals + (raid_ctlr_position == 0)) {
-                       this_device->expose_state = HPSA_DO_NOT_EXPOSE;
-               } else {
-                       this_device->expose_state =
-                                       HPSA_SG_ATTACH | HPSA_ULD_ATTACH;
-               }
+               /*
+                * Expose all devices except for physical devices that
+                * are masked.
+                */
+               if (MASKED_DEVICE(lunaddrbytes) && this_device->physical_device)
+                       this_device->expose_device = 0;
+               else
+                       this_device->expose_device = 1;
+
+
+               /*
+                * Get the SAS address for physical devices that are exposed.
+                */
+               if (this_device->physical_device && this_device->expose_device)
+                       hpsa_get_sas_address(h, lunaddrbytes, this_device);
 
                switch (this_device->devtype) {
                case TYPE_ROM:
@@ -3833,14 +4103,14 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                                ncurrent++;
                        break;
                case TYPE_DISK:
-                       if (i < nphysicals + (raid_ctlr_position == 0)) {
+                       if (this_device->physical_device) {
                                /* The disk is in HBA mode. */
                                /* Never use RAID mapper in HBA mode. */
                                this_device->offload_enabled = 0;
                                hpsa_get_ioaccel_drive_info(h, this_device,
-                                       lunaddrbytes, id_phys);
-                               hpsa_get_path_info(this_device, lunaddrbytes,
-                                                       id_phys);
+                                       physdev_list, phys_dev_index, id_phys);
+                               hpsa_get_path_info(this_device,
+                                       physdev_list, phys_dev_index, id_phys);
                        }
                        ncurrent++;
                        break;
@@ -3865,7 +4135,19 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
                if (ncurrent >= HPSA_MAX_DEVICES)
                        break;
        }
-       adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
+
+       if (h->sas_host == NULL) {
+               int rc = 0;
+
+               rc = hpsa_add_sas_host(h);
+               if (rc) {
+                       dev_warn(&h->pdev->dev,
+                               "Could not add sas host %d\n", rc);
+                       goto out;
+               }
+       }
+
+       adjust_hpsa_scsi_table(h, currentsd, ncurrent);
 out:
        kfree(tmpdevice);
        for (i = 0; i < ndev_allocated; i++)
@@ -3873,6 +4155,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        kfree(currentsd);
        kfree(physdev_list);
        kfree(logdev_list);
+       kfree(id_ctlr);
        kfree(id_phys);
 }
 
@@ -3978,19 +4261,14 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len)
        case READ_6:
        case READ_12:
                if (*cdb_len == 6) {
-                       block = (((u32) cdb[2]) << 8) | cdb[3];
+                       block = get_unaligned_be16(&cdb[2]);
                        block_cnt = cdb[4];
+                       if (block_cnt == 0)
+                               block_cnt = 256;
                } else {
                        BUG_ON(*cdb_len != 12);
-                       block = (((u32) cdb[2]) << 24) |
-                               (((u32) cdb[3]) << 16) |
-                               (((u32) cdb[4]) << 8) |
-                               cdb[5];
-                       block_cnt =
-                               (((u32) cdb[6]) << 24) |
-                               (((u32) cdb[7]) << 16) |
-                               (((u32) cdb[8]) << 8) |
-                               cdb[9];
+                       block = get_unaligned_be32(&cdb[2]);
+                       block_cnt = get_unaligned_be32(&cdb[6]);
                }
                if (block_cnt > 0xffff)
                        return IO_ACCEL_INELIGIBLE;
@@ -4272,6 +4550,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
        /* fill in sg elements */
        if (use_sg > h->ioaccel_maxsg) {
                cp->sg_count = 1;
+               cp->sg[0].length = cpu_to_le32(use_sg * sizeof(cp->sg[0]));
                if (hpsa_map_ioaccel2_sg_chain_block(h, cp, c)) {
                        atomic_dec(&phys_disk->ioaccel_cmds_out);
                        scsi_dma_unmap(cmd);
@@ -4376,9 +4655,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
        case WRITE_6:
                is_write = 1;
        case READ_6:
-               first_block =
-                       (((u64) cmd->cmnd[2]) << 8) |
-                       cmd->cmnd[3];
+               first_block = get_unaligned_be16(&cmd->cmnd[2]);
                block_cnt = cmd->cmnd[4];
                if (block_cnt == 0)
                        block_cnt = 256;
@@ -4947,7 +5224,7 @@ static void hpsa_scan_start(struct Scsi_Host *sh)
        if (unlikely(lockup_detected(h)))
                return hpsa_scan_complete(h);
 
-       hpsa_update_scsi_devices(h, h->scsi_host->host_no);
+       hpsa_update_scsi_devices(h);
 
        hpsa_scan_complete(h);
 }
@@ -4983,7 +5260,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh,
 static int hpsa_scsi_host_alloc(struct ctlr_info *h)
 {
        struct Scsi_Host *sh;
-       int error;
 
        sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
        if (sh == NULL) {
@@ -5001,17 +5277,11 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
        sh->can_queue = h->nr_cmds - HPSA_NRESERVED_CMDS;
        sh->cmd_per_lun = sh->can_queue;
        sh->sg_tablesize = h->maxsgentries;
+       sh->transportt = hpsa_sas_transport_template;
        sh->hostdata[0] = (unsigned long) h;
        sh->irq = h->intr[h->intr_mode];
        sh->unique_id = sh->irq;
-       error = scsi_init_shared_tag_map(sh, sh->can_queue);
-       if (error) {
-               dev_err(&h->pdev->dev,
-                       "%s: scsi_init_shared_tag_map failed for controller %d\n",
-                       __func__, h->ctlr);
-                       scsi_host_put(sh);
-                       return error;
-       }
+
        h->scsi_host = sh;
        return 0;
 }
@@ -5167,6 +5437,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
        int rc;
        struct ctlr_info *h;
        struct hpsa_scsi_dev_t *dev;
+       u8 reset_type;
        char msg[48];
 
        /* find the controller to which the command to be aborted was sent */
@@ -5205,14 +5476,25 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
        if (is_hba_lunid(dev->scsi3addr))
                return SUCCESS;
 
-       hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting");
+       if (is_logical_dev_addr_mode(dev->scsi3addr))
+               reset_type = HPSA_DEVICE_RESET_MSG;
+       else
+               reset_type = HPSA_PHYS_TARGET_RESET;
+
+       sprintf(msg, "resetting %s",
+               reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ");
+       hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
+
+       h->reset_in_progress = 1;
 
        /* send a reset to the SCSI LUN which the command was sent to */
-       rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN,
+       rc = hpsa_do_reset(h, dev, dev->scsi3addr, reset_type,
                           DEFAULT_REPLY_QUEUE);
-       snprintf(msg, sizeof(msg), "reset %s",
-                rc == 0 ? "completed successfully" : "failed");
+       sprintf(msg, "reset %s %s",
+               reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical ",
+               rc == 0 ? "completed successfully" : "failed");
        hpsa_show_dev_msg(KERN_WARNING, h, dev, msg);
+       h->reset_in_progress = 0;
        return rc == 0 ? SUCCESS : FAILED;
 }
 
@@ -6270,6 +6552,24 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        c->Request.CDB[8] = (size >> 8) & 0xFF;
                        c->Request.CDB[9] = size & 0xFF;
                        break;
+               case BMIC_SENSE_DIAG_OPTIONS:
+                       c->Request.CDBLen = 16;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+                       c->Request.Timeout = 0;
+                       /* Spec says this should be BMIC_WRITE */
+                       c->Request.CDB[0] = BMIC_READ;
+                       c->Request.CDB[6] = BMIC_SENSE_DIAG_OPTIONS;
+                       break;
+               case BMIC_SET_DIAG_OPTIONS:
+                       c->Request.CDBLen = 16;
+                       c->Request.type_attr_dir =
+                                       TYPE_ATTR_DIR(cmd_type,
+                                               ATTR_SIMPLE, XFER_WRITE);
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = BMIC_WRITE;
+                       c->Request.CDB[6] = BMIC_SET_DIAG_OPTIONS;
+                       break;
                case HPSA_CACHE_FLUSH:
                        c->Request.CDBLen = 12;
                        c->Request.type_attr_dir =
@@ -6319,6 +6619,32 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        c->Request.CDB[7] = (size >> 16) & 0xFF;
                        c->Request.CDB[8] = (size >> 8) & 0XFF;
                        break;
+               case BMIC_SENSE_SUBSYSTEM_INFORMATION:
+                       c->Request.CDBLen = 10;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = BMIC_READ;
+                       c->Request.CDB[6] = BMIC_SENSE_SUBSYSTEM_INFORMATION;
+                       c->Request.CDB[7] = (size >> 16) & 0xFF;
+                       c->Request.CDB[8] = (size >> 8) & 0XFF;
+                       break;
+               case BMIC_IDENTIFY_CONTROLLER:
+                       c->Request.CDBLen = 10;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
+                       c->Request.Timeout = 0;
+                       c->Request.CDB[0] = BMIC_READ;
+                       c->Request.CDB[1] = 0;
+                       c->Request.CDB[2] = 0;
+                       c->Request.CDB[3] = 0;
+                       c->Request.CDB[4] = 0;
+                       c->Request.CDB[5] = 0;
+                       c->Request.CDB[6] = BMIC_IDENTIFY_CONTROLLER;
+                       c->Request.CDB[7] = (size >> 16) & 0xFF;
+                       c->Request.CDB[8] = (size >> 8) & 0XFF;
+                       c->Request.CDB[9] = 0;
+                       break;
                default:
                        dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
                        BUG();
@@ -6327,6 +6653,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
        } else if (cmd_type == TYPE_MSG) {
                switch (cmd) {
 
+               case  HPSA_PHYS_TARGET_RESET:
+                       c->Request.CDBLen = 16;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
+                       c->Request.Timeout = 0; /* Don't time out */
+                       memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
+                       c->Request.CDB[0] = HPSA_RESET;
+                       c->Request.CDB[1] = HPSA_TARGET_RESET_TYPE;
+                       /* Physical target reset needs no control bytes 4-7*/
+                       c->Request.CDB[4] = 0x00;
+                       c->Request.CDB[5] = 0x00;
+                       c->Request.CDB[6] = 0x00;
+                       c->Request.CDB[7] = 0x00;
+                       break;
                case  HPSA_DEVICE_RESET_MSG:
                        c->Request.CDBLen = 16;
                        c->Request.type_attr_dir =
@@ -6440,16 +6780,6 @@ static inline void finish_cmd(struct CommandList *c)
                complete(c->waiting);
 }
 
-
-static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag)
-{
-#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
-#define HPSA_SIMPLE_ERROR_BITS 0x03
-       if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
-               return tag & ~HPSA_SIMPLE_ERROR_BITS;
-       return tag & ~HPSA_PERF_ERROR_BITS;
-}
-
 /* process completion of an indexed ("direct lookup") command */
 static inline void process_indexed_cmd(struct ctlr_info *h,
        u32 raw_tag)
@@ -7860,6 +8190,11 @@ static void hpsa_ack_ctlr_events(struct ctlr_info *h)
  */
 static int hpsa_ctlr_needs_rescan(struct ctlr_info *h)
 {
+       if (h->drv_req_rescan) {
+               h->drv_req_rescan = 0;
+               return 1;
+       }
+
        if (!(h->fw_support & MISC_FW_EVENT_NOTIFY))
                return 0;
 
@@ -7893,6 +8228,41 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h)
        return 0;
 }
 
+static int hpsa_luns_changed(struct ctlr_info *h)
+{
+       int rc = 1; /* assume there are changes */
+       struct ReportLUNdata *logdev = NULL;
+
+       /* if we can't find out if lun data has changed,
+        * assume that it has.
+        */
+
+       if (!h->lastlogicals)
+               goto out;
+
+       logdev = kzalloc(sizeof(*logdev), GFP_KERNEL);
+       if (!logdev) {
+               dev_warn(&h->pdev->dev,
+                       "Out of memory, can't track lun changes.\n");
+               goto out;
+       }
+       if (hpsa_scsi_do_report_luns(h, 1, logdev, sizeof(*logdev), 0)) {
+               dev_warn(&h->pdev->dev,
+                       "report luns failed, can't track lun changes.\n");
+               goto out;
+       }
+       if (memcmp(logdev, h->lastlogicals, sizeof(*logdev))) {
+               dev_info(&h->pdev->dev,
+                       "Lun changes detected.\n");
+               memcpy(h->lastlogicals, logdev, sizeof(*logdev));
+               goto out;
+       } else
+               rc = 0; /* no changes detected. */
+out:
+       kfree(logdev);
+       return rc;
+}
+
 static void hpsa_rescan_ctlr_worker(struct work_struct *work)
 {
        unsigned long flags;
@@ -7908,6 +8278,19 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work)
                hpsa_ack_ctlr_events(h);
                hpsa_scan_start(h->scsi_host);
                scsi_host_put(h->scsi_host);
+       } else if (h->discovery_polling) {
+               hpsa_disable_rld_caching(h);
+               if (hpsa_luns_changed(h)) {
+                       struct Scsi_Host *sh = NULL;
+
+                       dev_info(&h->pdev->dev,
+                               "driver discovery polling rescan.\n");
+                       sh = scsi_host_get(h->scsi_host);
+                       if (sh != NULL) {
+                               hpsa_scan_start(sh);
+                               scsi_host_put(sh);
+                       }
+               }
        }
        spin_lock_irqsave(&h->lock, flags);
        if (!h->remove_in_progress)
@@ -8148,6 +8531,8 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* Enable Accelerated IO path at driver layer */
        h->acciopath_status = 1;
+       /* Disable discovery polling.*/
+       h->discovery_polling = 0;
 
 
        /* Turn the interrupts on so we can service requests */
@@ -8155,6 +8540,11 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        hpsa_hba_inquiry(h);
 
+       h->lastlogicals = kzalloc(sizeof(*(h->lastlogicals)), GFP_KERNEL);
+       if (!h->lastlogicals)
+               dev_info(&h->pdev->dev,
+                       "Can't track change to report lun data\n");
+
        /* Monitor the controller for firmware lockups */
        h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
        INIT_DELAYED_WORK(&h->monitor_ctlr_work, hpsa_monitor_ctlr_worker);
@@ -8227,6 +8617,71 @@ static void hpsa_flush_cache(struct ctlr_info *h)
        kfree(flush_buf);
 }
 
+/* Make controller gather fresh report lun data each time we
+ * send down a report luns request
+ */
+static void hpsa_disable_rld_caching(struct ctlr_info *h)
+{
+       u32 *options;
+       struct CommandList *c;
+       int rc;
+
+       /* Don't bother trying to set diag options if locked up */
+       if (unlikely(h->lockup_detected))
+               return;
+
+       options = kzalloc(sizeof(*options), GFP_KERNEL);
+       if (!options) {
+               dev_err(&h->pdev->dev,
+                       "Error: failed to disable rld caching, during alloc.\n");
+               return;
+       }
+
+       c = cmd_alloc(h);
+
+       /* first, get the current diag options settings */
+       if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0,
+               RAID_CTLR_LUNID, TYPE_CMD))
+               goto errout;
+
+       rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+               PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+       if ((rc != 0) || (c->err_info->CommandStatus != 0))
+               goto errout;
+
+       /* Now, set the bit for disabling the RLD caching */
+       *options |= HPSA_DIAG_OPTS_DISABLE_RLD_CACHING;
+
+       if (fill_cmd(c, BMIC_SET_DIAG_OPTIONS, h, options, 4, 0,
+               RAID_CTLR_LUNID, TYPE_CMD))
+               goto errout;
+
+       rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+               PCI_DMA_TODEVICE, NO_TIMEOUT);
+       if ((rc != 0)  || (c->err_info->CommandStatus != 0))
+               goto errout;
+
+       /* Now verify that it got set: */
+       if (fill_cmd(c, BMIC_SENSE_DIAG_OPTIONS, h, options, 4, 0,
+               RAID_CTLR_LUNID, TYPE_CMD))
+               goto errout;
+
+       rc = hpsa_scsi_do_simple_cmd_with_retry(h, c,
+               PCI_DMA_FROMDEVICE, NO_TIMEOUT);
+       if ((rc != 0)  || (c->err_info->CommandStatus != 0))
+               goto errout;
+
+       if (*options && HPSA_DIAG_OPTS_DISABLE_RLD_CACHING)
+               goto out;
+
+errout:
+       dev_err(&h->pdev->dev,
+                       "Error: failed to disable report lun data caching.\n");
+out:
+       cmd_free(h, c);
+       kfree(options);
+}
+
 static void hpsa_shutdown(struct pci_dev *pdev)
 {
        struct ctlr_info *h;
@@ -8292,6 +8747,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
        hpsa_free_performant_mode(h);                   /* init_one 7 */
        hpsa_free_sg_chain_blocks(h);                   /* init_one 6 */
        hpsa_free_cmd_pool(h);                          /* init_one 5 */
+       kfree(h->lastlogicals);
 
        /* hpsa_free_irqs already called via hpsa_shutdown init_one 4 */
 
@@ -8304,6 +8760,9 @@ static void hpsa_remove_one(struct pci_dev *pdev)
        free_percpu(h->lockup_detected);                /* init_one 2 */
        h->lockup_detected = NULL;                      /* init_one 2 */
        /* (void) pci_disable_pcie_error_reporting(pdev); */    /* init_one 1 */
+
+       hpsa_delete_sas_host(h);
+
        kfree(h);                                       /* init_one 1 */
 }
 
@@ -8766,18 +9225,369 @@ static void hpsa_drain_accel_commands(struct ctlr_info *h)
        } while (1);
 }
 
+static struct hpsa_sas_phy *hpsa_alloc_sas_phy(
+                               struct hpsa_sas_port *hpsa_sas_port)
+{
+       struct hpsa_sas_phy *hpsa_sas_phy;
+       struct sas_phy *phy;
+
+       hpsa_sas_phy = kzalloc(sizeof(*hpsa_sas_phy), GFP_KERNEL);
+       if (!hpsa_sas_phy)
+               return NULL;
+
+       phy = sas_phy_alloc(hpsa_sas_port->parent_node->parent_dev,
+               hpsa_sas_port->next_phy_index);
+       if (!phy) {
+               kfree(hpsa_sas_phy);
+               return NULL;
+       }
+
+       hpsa_sas_port->next_phy_index++;
+       hpsa_sas_phy->phy = phy;
+       hpsa_sas_phy->parent_port = hpsa_sas_port;
+
+       return hpsa_sas_phy;
+}
+
+static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy)
+{
+       struct sas_phy *phy = hpsa_sas_phy->phy;
+
+       sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy);
+       sas_phy_free(phy);
+       if (hpsa_sas_phy->added_to_port)
+               list_del(&hpsa_sas_phy->phy_list_entry);
+       kfree(hpsa_sas_phy);
+}
+
+static int hpsa_sas_port_add_phy(struct hpsa_sas_phy *hpsa_sas_phy)
+{
+       int rc;
+       struct hpsa_sas_port *hpsa_sas_port;
+       struct sas_phy *phy;
+       struct sas_identify *identify;
+
+       hpsa_sas_port = hpsa_sas_phy->parent_port;
+       phy = hpsa_sas_phy->phy;
+
+       identify = &phy->identify;
+       memset(identify, 0, sizeof(*identify));
+       identify->sas_address = hpsa_sas_port->sas_address;
+       identify->device_type = SAS_END_DEVICE;
+       identify->initiator_port_protocols = SAS_PROTOCOL_STP;
+       identify->target_port_protocols = SAS_PROTOCOL_STP;
+       phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
+       phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
+       phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN;
+       phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN;
+       phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+
+       rc = sas_phy_add(hpsa_sas_phy->phy);
+       if (rc)
+               return rc;
+
+       sas_port_add_phy(hpsa_sas_port->port, hpsa_sas_phy->phy);
+       list_add_tail(&hpsa_sas_phy->phy_list_entry,
+                       &hpsa_sas_port->phy_list_head);
+       hpsa_sas_phy->added_to_port = true;
+
+       return 0;
+}
+
+static int
+       hpsa_sas_port_add_rphy(struct hpsa_sas_port *hpsa_sas_port,
+                               struct sas_rphy *rphy)
+{
+       struct sas_identify *identify;
+
+       identify = &rphy->identify;
+       identify->sas_address = hpsa_sas_port->sas_address;
+       identify->initiator_port_protocols = SAS_PROTOCOL_STP;
+       identify->target_port_protocols = SAS_PROTOCOL_STP;
+
+       return sas_rphy_add(rphy);
+}
+
+static struct hpsa_sas_port
+       *hpsa_alloc_sas_port(struct hpsa_sas_node *hpsa_sas_node,
+                               u64 sas_address)
+{
+       int rc;
+       struct hpsa_sas_port *hpsa_sas_port;
+       struct sas_port *port;
+
+       hpsa_sas_port = kzalloc(sizeof(*hpsa_sas_port), GFP_KERNEL);
+       if (!hpsa_sas_port)
+               return NULL;
+
+       INIT_LIST_HEAD(&hpsa_sas_port->phy_list_head);
+       hpsa_sas_port->parent_node = hpsa_sas_node;
+
+       port = sas_port_alloc_num(hpsa_sas_node->parent_dev);
+       if (!port)
+               goto free_hpsa_port;
+
+       rc = sas_port_add(port);
+       if (rc)
+               goto free_sas_port;
+
+       hpsa_sas_port->port = port;
+       hpsa_sas_port->sas_address = sas_address;
+       list_add_tail(&hpsa_sas_port->port_list_entry,
+                       &hpsa_sas_node->port_list_head);
+
+       return hpsa_sas_port;
+
+free_sas_port:
+       sas_port_free(port);
+free_hpsa_port:
+       kfree(hpsa_sas_port);
+
+       return NULL;
+}
+
+static void hpsa_free_sas_port(struct hpsa_sas_port *hpsa_sas_port)
+{
+       struct hpsa_sas_phy *hpsa_sas_phy;
+       struct hpsa_sas_phy *next;
+
+       list_for_each_entry_safe(hpsa_sas_phy, next,
+                       &hpsa_sas_port->phy_list_head, phy_list_entry)
+               hpsa_free_sas_phy(hpsa_sas_phy);
+
+       sas_port_delete(hpsa_sas_port->port);
+       list_del(&hpsa_sas_port->port_list_entry);
+       kfree(hpsa_sas_port);
+}
+
+static struct hpsa_sas_node *hpsa_alloc_sas_node(struct device *parent_dev)
+{
+       struct hpsa_sas_node *hpsa_sas_node;
+
+       hpsa_sas_node = kzalloc(sizeof(*hpsa_sas_node), GFP_KERNEL);
+       if (hpsa_sas_node) {
+               hpsa_sas_node->parent_dev = parent_dev;
+               INIT_LIST_HEAD(&hpsa_sas_node->port_list_head);
+       }
+
+       return hpsa_sas_node;
+}
+
+static void hpsa_free_sas_node(struct hpsa_sas_node *hpsa_sas_node)
+{
+       struct hpsa_sas_port *hpsa_sas_port;
+       struct hpsa_sas_port *next;
+
+       if (!hpsa_sas_node)
+               return;
+
+       list_for_each_entry_safe(hpsa_sas_port, next,
+                       &hpsa_sas_node->port_list_head, port_list_entry)
+               hpsa_free_sas_port(hpsa_sas_port);
+
+       kfree(hpsa_sas_node);
+}
+
+static struct hpsa_scsi_dev_t
+       *hpsa_find_device_by_sas_rphy(struct ctlr_info *h,
+                                       struct sas_rphy *rphy)
+{
+       int i;
+       struct hpsa_scsi_dev_t *device;
+
+       for (i = 0; i < h->ndevices; i++) {
+               device = h->dev[i];
+               if (!device->sas_port)
+                       continue;
+               if (device->sas_port->rphy == rphy)
+                       return device;
+       }
+
+       return NULL;
+}
+
+static int hpsa_add_sas_host(struct ctlr_info *h)
+{
+       int rc;
+       struct device *parent_dev;
+       struct hpsa_sas_node *hpsa_sas_node;
+       struct hpsa_sas_port *hpsa_sas_port;
+       struct hpsa_sas_phy *hpsa_sas_phy;
+
+       parent_dev = &h->scsi_host->shost_gendev;
+
+       hpsa_sas_node = hpsa_alloc_sas_node(parent_dev);
+       if (!hpsa_sas_node)
+               return -ENOMEM;
+
+       hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, h->sas_address);
+       if (!hpsa_sas_port) {
+               rc = -ENODEV;
+               goto free_sas_node;
+       }
+
+       hpsa_sas_phy = hpsa_alloc_sas_phy(hpsa_sas_port);
+       if (!hpsa_sas_phy) {
+               rc = -ENODEV;
+               goto free_sas_port;
+       }
+
+       rc = hpsa_sas_port_add_phy(hpsa_sas_phy);
+       if (rc)
+               goto free_sas_phy;
+
+       h->sas_host = hpsa_sas_node;
+
+       return 0;
+
+free_sas_phy:
+       hpsa_free_sas_phy(hpsa_sas_phy);
+free_sas_port:
+       hpsa_free_sas_port(hpsa_sas_port);
+free_sas_node:
+       hpsa_free_sas_node(hpsa_sas_node);
+
+       return rc;
+}
+
+static void hpsa_delete_sas_host(struct ctlr_info *h)
+{
+       hpsa_free_sas_node(h->sas_host);
+}
+
+static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node,
+                               struct hpsa_scsi_dev_t *device)
+{
+       int rc;
+       struct hpsa_sas_port *hpsa_sas_port;
+       struct sas_rphy *rphy;
+
+       hpsa_sas_port = hpsa_alloc_sas_port(hpsa_sas_node, device->sas_address);
+       if (!hpsa_sas_port)
+               return -ENOMEM;
+
+       rphy = sas_end_device_alloc(hpsa_sas_port->port);
+       if (!rphy) {
+               rc = -ENODEV;
+               goto free_sas_port;
+       }
+
+       hpsa_sas_port->rphy = rphy;
+       device->sas_port = hpsa_sas_port;
+
+       rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy);
+       if (rc)
+               goto free_sas_port;
+
+       return 0;
+
+free_sas_port:
+       hpsa_free_sas_port(hpsa_sas_port);
+       device->sas_port = NULL;
+
+       return rc;
+}
+
+static void hpsa_remove_sas_device(struct hpsa_scsi_dev_t *device)
+{
+       if (device->sas_port) {
+               hpsa_free_sas_port(device->sas_port);
+               device->sas_port = NULL;
+       }
+}
+
+static int
+hpsa_sas_get_linkerrors(struct sas_phy *phy)
+{
+       return 0;
+}
+
+static int
+hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
+{
+       return 0;
+}
+
+static int
+hpsa_sas_get_bay_identifier(struct sas_rphy *rphy)
+{
+       return -ENXIO;
+}
+
+static int
+hpsa_sas_phy_reset(struct sas_phy *phy, int hard_reset)
+{
+       return 0;
+}
+
+static int
+hpsa_sas_phy_enable(struct sas_phy *phy, int enable)
+{
+       return 0;
+}
+
+static int
+hpsa_sas_phy_setup(struct sas_phy *phy)
+{
+       return 0;
+}
+
+static void
+hpsa_sas_phy_release(struct sas_phy *phy)
+{
+}
+
+static int
+hpsa_sas_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
+{
+       return -EINVAL;
+}
+
+/* SMP = Serial Management Protocol */
+static int
+hpsa_sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+struct request *req)
+{
+       return -EINVAL;
+}
+
+static struct sas_function_template hpsa_sas_transport_functions = {
+       .get_linkerrors = hpsa_sas_get_linkerrors,
+       .get_enclosure_identifier = hpsa_sas_get_enclosure_identifier,
+       .get_bay_identifier = hpsa_sas_get_bay_identifier,
+       .phy_reset = hpsa_sas_phy_reset,
+       .phy_enable = hpsa_sas_phy_enable,
+       .phy_setup = hpsa_sas_phy_setup,
+       .phy_release = hpsa_sas_phy_release,
+       .set_phy_speed = hpsa_sas_phy_speed,
+       .smp_handler = hpsa_sas_smp_handler,
+};
+
 /*
  *  This is it.  Register the PCI driver information for the cards we control
  *  the OS will call our registered routines when it finds one of our cards.
  */
 static int __init hpsa_init(void)
 {
-       return pci_register_driver(&hpsa_pci_driver);
+       int rc;
+
+       hpsa_sas_transport_template =
+               sas_attach_transport(&hpsa_sas_transport_functions);
+       if (!hpsa_sas_transport_template)
+               return -ENODEV;
+
+       rc = pci_register_driver(&hpsa_pci_driver);
+
+       if (rc)
+               sas_release_transport(hpsa_sas_transport_template);
+
+       return rc;
 }
 
 static void __exit hpsa_cleanup(void)
 {
        pci_unregister_driver(&hpsa_pci_driver);
+       sas_release_transport(hpsa_sas_transport_template);
 }
 
 static void __attribute__((unused)) verify_offsets(void)
index 27debb363529ec88cbac6f364a3538b64d32b7a7..ae5beda1bdb517849652a68a900c241057ab3ce2 100644 (file)
@@ -33,12 +33,38 @@ struct access_method {
        unsigned long (*command_completed)(struct ctlr_info *h, u8 q);
 };
 
+/* for SAS hosts and SAS expanders */
+struct hpsa_sas_node {
+       struct device *parent_dev;
+       struct list_head port_list_head;
+};
+
+struct hpsa_sas_port {
+       struct list_head port_list_entry;
+       u64 sas_address;
+       struct sas_port *port;
+       int next_phy_index;
+       struct list_head phy_list_head;
+       struct hpsa_sas_node *parent_node;
+       struct sas_rphy *rphy;
+};
+
+struct hpsa_sas_phy {
+       struct list_head phy_list_entry;
+       struct sas_phy *phy;
+       struct hpsa_sas_port *parent_port;
+       bool added_to_port;
+};
+
 struct hpsa_scsi_dev_t {
-       int devtype;
+       unsigned int devtype;
        int bus, target, lun;           /* as presented to the OS */
        unsigned char scsi3addr[8];     /* as presented to the HW */
+       u8 physical_device : 1;
+       u8 expose_device;
 #define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
        unsigned char device_id[16];    /* from inquiry pg. 0x83 */
+       u64 sas_address;
        unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
        unsigned char model[16];        /* bytes 16-31 of inquiry data */
        unsigned char raid_level;       /* from inquiry page 0xC1 */
@@ -75,11 +101,8 @@ struct hpsa_scsi_dev_t {
        struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES];
        int nphysical_disks;
        int supports_aborts;
-#define HPSA_DO_NOT_EXPOSE     0x0
-#define HPSA_SG_ATTACH         0x1
-#define HPSA_ULD_ATTACH                0x2
-#define HPSA_SCSI_ADD          (HPSA_SG_ATTACH | HPSA_ULD_ATTACH)
-       u8 expose_state;
+       struct hpsa_sas_port *sas_port;
+       int external;   /* 1-from external array 0-not <0-unknown */
 };
 
 struct reply_queue_buffer {
@@ -136,6 +159,7 @@ struct ctlr_info {
        char    *product_name;
        struct pci_dev *pdev;
        u32     board_id;
+       u64     sas_address;
        void __iomem *vaddr;
        unsigned long paddr;
        int     nr_cmds; /* Number of commands allowed on this controller */
@@ -262,7 +286,10 @@ struct ctlr_info {
        spinlock_t offline_device_lock;
        struct list_head offline_device_list;
        int     acciopath_status;
+       int     drv_req_rescan;
        int     raid_offload_debug;
+       int     discovery_polling;
+       struct  ReportLUNdata *lastlogicals;
        int     needs_abort_tags_swizzled;
        struct workqueue_struct *resubmit_wq;
        struct workqueue_struct *rescan_ctlr_wq;
@@ -270,6 +297,8 @@ struct ctlr_info {
        wait_queue_head_t abort_cmd_wait_queue;
        wait_queue_head_t event_sync_wait_queue;
        struct mutex reset_mutex;
+       u8 reset_in_progress;
+       struct hpsa_sas_node *sas_host;
 };
 
 struct offline_device_entry {
@@ -283,6 +312,7 @@ struct offline_device_entry {
 #define HPSA_RESET_TYPE_BUS 0x01
 #define HPSA_RESET_TYPE_TARGET 0x03
 #define HPSA_RESET_TYPE_LUN 0x04
+#define HPSA_PHYS_TARGET_RESET 0x99 /* not defined by cciss spec */
 #define HPSA_MSG_SEND_RETRY_LIMIT 10
 #define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS (10000)
 
@@ -367,6 +397,11 @@ struct offline_device_entry {
 #define IOACCEL2_INBOUND_POSTQ_64_LOW  0xd0
 #define IOACCEL2_INBOUND_POSTQ_64_HI   0xd4
 
+#define HPSA_PHYSICAL_DEVICE_BUS       0
+#define HPSA_RAID_VOLUME_BUS           1
+#define HPSA_EXTERNAL_RAID_VOLUME_BUS  2
+#define HPSA_HBA_BUS                   3
+
 /*
        Send the command to the hardware
 */
index 47c756ba8dce414ce7302e3198359eda8223c327..d92ef0d352b55fa6d8d1fb0f9ef6e7c50b5ec3db 100644 (file)
@@ -260,8 +260,6 @@ struct ext_report_lun_entry {
        u8 wwid[8];
        u8 device_type;
        u8 device_flags;
-#define NON_DISK_PHYS_DEV(x) ((x)[17] & 0x01)
-#define PHYS_IOACCEL(x) ((x)[17] & 0x08)
        u8 lun_count; /* multi-lun device, how many luns */
        u8 redundant_paths;
        u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */
@@ -288,6 +286,11 @@ struct SenseSubsystem_info {
 #define BMIC_FLASH_FIRMWARE 0xF7
 #define BMIC_SENSE_CONTROLLER_PARAMETERS 0x64
 #define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15
+#define BMIC_IDENTIFY_CONTROLLER 0x11
+#define BMIC_SET_DIAG_OPTIONS 0xF4
+#define BMIC_SENSE_DIAG_OPTIONS 0xF5
+#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000
+#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66
 
 /* Command List Structure */
 union SCSI3Addr {
@@ -684,6 +687,16 @@ struct hpsa_pci_info {
        u32             board_id;
 };
 
+struct bmic_identify_controller {
+       u8      configured_logical_drive_count; /* offset 0 */
+       u8      pad1[153];
+       __le16  extended_logical_unit_count;    /* offset 154 */
+       u8      pad2[136];
+       u8      controller_mode;        /* offset 292 */
+       u8      pad3[32];
+};
+
+
 struct bmic_identify_physical_device {
        u8    scsi_bus;          /* SCSI Bus number on controller */
        u8    scsi_id;           /* SCSI ID on this bus */
@@ -816,5 +829,18 @@ struct bmic_identify_physical_device {
        u8     padding[112];
 };
 
+struct bmic_sense_subsystem_info {
+       u8      primary_slot_number;
+       u8      reserved[3];
+       u8      chasis_serial_number[32];
+       u8      primary_world_wide_id[8];
+       u8      primary_array_serial_number[32]; /* NULL terminated */
+       u8      primary_cache_serial_number[32]; /* NULL terminated */
+       u8      reserved_2[8];
+       u8      secondary_array_serial_number[32];
+       u8      secondary_cache_serial_number[32];
+       u8      pad[332];
+};
+
 #pragma pack()
 #endif /* HPSA_CMD_H */
index 057d27721d5b24d23e24c3040b64507507556400..6aa317c303e2dced686c76cc1102e563b4f058b1 100644 (file)
@@ -3095,7 +3095,6 @@ static struct scsi_host_template driver_template = {
        .max_sectors = IBMVFC_MAX_SECTORS,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ibmvfc_attrs,
-       .use_blk_tags = 1,
        .track_queue_depth = 1,
 };
 
index 6a41c36b16b0d5dfe5edc663988388dbf71e24cd..adfef9db6f1e2c279002315abc3d936adc622027 100644 (file)
@@ -106,9 +106,9 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(IBMVSCSI_VERSION);
 
 module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_id, "Largest ID value for each channel");
+MODULE_PARM_DESC(max_id, "Largest ID value for each channel [Default=64]");
 module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_channel, "Largest channel value");
+MODULE_PARM_DESC(max_channel, "Largest channel value [Default=3]");
 module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds");
 module_param_named(max_requests, max_requests, int, S_IRUGO);
@@ -2289,11 +2289,15 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
                goto init_pool_failed;
        }
 
-       host->max_lun = 8;
+       host->max_lun = IBMVSCSI_MAX_LUN;
        host->max_id = max_id;
        host->max_channel = max_channel;
        host->max_cmd_len = 16;
 
+       dev_info(dev,
+                "Maximum ID: %d Maximum LUN: %llu Maximum Channel: %d\n",
+                host->max_id, host->max_lun, host->max_channel);
+
        if (scsi_add_host(hostdata->host, hostdata->dev))
                goto add_host_failed;
 
index 7d64867c5dd1784cb4a3e265bed621346e334d16..1067367395cd4fa216f160cf6578195c42e7cbd0 100644 (file)
@@ -48,6 +48,7 @@ struct Scsi_Host;
 #define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
 #define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
 #define IBMVSCSI_MAX_CMDS_PER_LUN 64
+#define IBMVSCSI_MAX_LUN 32
 
 /* ------------------------------------------------------------
  * Data Structures
index b62836ddbbee55c1fc7d6c65f4926a281fff387b..536cd5a8042245f4ad46929a256098e047d745dd 100644 (file)
@@ -6363,15 +6363,19 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
        ipr_cmd->scsi_cmd = scsi_cmd;
        ipr_cmd->done = ipr_scsi_eh_done;
 
-       if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) {
+       if (ipr_is_gscsi(res)) {
                if (scsi_cmd->underflow == 0)
                        ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK;
 
-               ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
-               if (ipr_is_gscsi(res) && res->reset_occurred) {
+               if (res->reset_occurred) {
                        res->reset_occurred = 0;
                        ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
                }
+       }
+
+       if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) {
+               ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC;
+
                ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR;
                if (scsi_cmd->flags & SCMD_TAGGED)
                        ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK;
@@ -6502,7 +6506,6 @@ static struct scsi_host_template driver_template = {
        .shost_attrs = ipr_ioa_attrs,
        .sdev_attrs = ipr_dev_attrs,
        .proc_name = IPR_NAME,
-       .use_blk_tags = 1,
 };
 
 /**
@@ -7671,6 +7674,63 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
        return IPR_RC_JOB_RETURN;
 }
 
+static int ipr_ioa_service_action_failed(struct ipr_cmnd *ipr_cmd)
+{
+       u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
+
+       if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT)
+               return IPR_RC_JOB_CONTINUE;
+
+       return ipr_reset_cmd_failed(ipr_cmd);
+}
+
+static void ipr_build_ioa_service_action(struct ipr_cmnd *ipr_cmd,
+                                        __be32 res_handle, u8 sa_code)
+{
+       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+
+       ioarcb->res_handle = res_handle;
+       ioarcb->cmd_pkt.cdb[0] = IPR_IOA_SERVICE_ACTION;
+       ioarcb->cmd_pkt.cdb[1] = sa_code;
+       ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD;
+}
+
+/**
+ * ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service
+ * action
+ *
+ * Return value:
+ *     none
+ **/
+static int ipr_ioafp_set_caching_parameters(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data;
+
+       ENTER;
+
+       ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+
+       if (pageC4->cache_cap[0] & IPR_CAP_SYNC_CACHE) {
+               ipr_build_ioa_service_action(ipr_cmd,
+                                            cpu_to_be32(IPR_IOA_RES_HANDLE),
+                                            IPR_IOA_SA_CHANGE_CACHE_PARAMS);
+
+               ioarcb->cmd_pkt.cdb[2] = 0x40;
+
+               ipr_cmd->job_step_failed = ipr_ioa_service_action_failed;
+               ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout,
+                          IPR_SET_SUP_DEVICE_TIMEOUT);
+
+               LEAVE;
+               return IPR_RC_JOB_RETURN;
+       }
+
+       LEAVE;
+       return IPR_RC_JOB_CONTINUE;
+}
+
 /**
  * ipr_ioafp_inquiry - Send an Inquiry to the adapter.
  * @ipr_cmd:   ipr command struct
@@ -7721,6 +7781,39 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page)
        return 0;
 }
 
+/**
+ * ipr_ioafp_pageC4_inquiry - Send a Page 0xC4 Inquiry to the adapter.
+ * @ipr_cmd:   ipr command struct
+ *
+ * This function sends a Page 0xC4 inquiry to the adapter
+ * to retrieve software VPD information.
+ *
+ * Return value:
+ *     IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_ioafp_pageC4_inquiry(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+       struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data;
+       struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data;
+
+       ENTER;
+       ipr_cmd->job_step = ipr_ioafp_set_caching_parameters;
+       memset(pageC4, 0, sizeof(*pageC4));
+
+       if (ipr_inquiry_page_supported(page0, 0xC4)) {
+               ipr_ioafp_inquiry(ipr_cmd, 1, 0xC4,
+                                 (ioa_cfg->vpd_cbs_dma
+                                  + offsetof(struct ipr_misc_cbs,
+                                             pageC4_data)),
+                                 sizeof(struct ipr_inquiry_pageC4));
+               return IPR_RC_JOB_RETURN;
+       }
+
+       LEAVE;
+       return IPR_RC_JOB_CONTINUE;
+}
+
 /**
  * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter.
  * @ipr_cmd:   ipr command struct
@@ -7738,7 +7831,7 @@ static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd)
        struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
 
        ENTER;
-       ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
+       ipr_cmd->job_step = ipr_ioafp_pageC4_inquiry;
        memset(cap, 0, sizeof(*cap));
 
        if (ipr_inquiry_page_supported(page0, 0xD0)) {
@@ -8277,6 +8370,42 @@ static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd)
        return IPR_RC_JOB_RETURN;
 }
 
+static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd)
+{
+       struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+       ENTER;
+
+       if (ioa_cfg->sdt_state != GET_DUMP)
+               return IPR_RC_JOB_RETURN;
+
+       if (!ioa_cfg->sis64 || !ipr_cmd->u.time_left ||
+           (readl(ioa_cfg->regs.sense_interrupt_reg) &
+            IPR_PCII_MAILBOX_STABLE)) {
+
+               if (!ipr_cmd->u.time_left)
+                       dev_err(&ioa_cfg->pdev->dev,
+                               "Timed out waiting for Mailbox register.\n");
+
+               ioa_cfg->sdt_state = READ_DUMP;
+               ioa_cfg->dump_timeout = 0;
+               if (ioa_cfg->sis64)
+                       ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
+               else
+                       ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
+               ipr_cmd->job_step = ipr_reset_wait_for_dump;
+               schedule_work(&ioa_cfg->work_q);
+
+       } else {
+               ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+               ipr_reset_start_timer(ipr_cmd,
+                                     IPR_CHECK_FOR_RESET_TIMEOUT);
+       }
+
+       LEAVE;
+       return IPR_RC_JOB_RETURN;
+}
+
 /**
  * ipr_reset_restore_cfg_space - Restore PCI config space.
  * @ipr_cmd:   ipr command struct
@@ -8326,20 +8455,11 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
 
        if (ioa_cfg->in_ioa_bringdown) {
                ipr_cmd->job_step = ipr_ioa_bringdown_done;
+       } else if (ioa_cfg->sdt_state == GET_DUMP) {
+               ipr_cmd->job_step = ipr_dump_mailbox_wait;
+               ipr_cmd->u.time_left = IPR_WAIT_FOR_MAILBOX;
        } else {
                ipr_cmd->job_step = ipr_reset_enable_ioa;
-
-               if (GET_DUMP == ioa_cfg->sdt_state) {
-                       ioa_cfg->sdt_state = READ_DUMP;
-                       ioa_cfg->dump_timeout = 0;
-                       if (ioa_cfg->sis64)
-                               ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT);
-                       else
-                               ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT);
-                       ipr_cmd->job_step = ipr_reset_wait_for_dump;
-                       schedule_work(&ioa_cfg->work_q);
-                       return IPR_RC_JOB_RETURN;
-               }
        }
 
        LEAVE;
index e4fb17a58649e22c110ae92490e0368a5e595505..a34c7a5a995e4bcbf61b1d859fb784b60a9cdbee 100644 (file)
@@ -39,8 +39,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.6.2"
-#define IPR_DRIVER_DATE "(June 11, 2015)"
+#define IPR_DRIVER_VERSION "2.6.3"
+#define IPR_DRIVER_DATE "(October 17, 2015)"
 
 /*
  * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
 #define IPR_SET_ALL_SUPPORTED_DEVICES                  0x80
 #define IPR_IOA_SHUTDOWN                               0xF7
 #define        IPR_WR_BUF_DOWNLOAD_AND_SAVE                    0x05
+#define IPR_IOA_SERVICE_ACTION                         0xD2
+
+/* IOA Service Actions */
+#define IPR_IOA_SA_CHANGE_CACHE_PARAMS                 0x14
 
 /*
  * Timeouts
 #define IPR_IPL_INIT_STAGE_TIME_MASK                   0x0000ffff
 #define IPR_PCII_IPL_STAGE_CHANGE                      (0x80000000 >> 0)
 
+#define IPR_PCII_MAILBOX_STABLE                                (0x80000000 >> 4)
+#define IPR_WAIT_FOR_MAILBOX                           (2 * HZ)
+
 #define IPR_PCII_IOA_TRANS_TO_OPER                     (0x80000000 >> 0)
 #define IPR_PCII_IOARCB_XFER_FAILED                    (0x80000000 >> 3)
 #define IPR_PCII_IOA_UNIT_CHECKED                      (0x80000000 >> 4)
@@ -846,6 +853,16 @@ struct ipr_inquiry_page0 {
        u8 page[IPR_INQUIRY_PAGE0_ENTRIES];
 }__attribute__((packed));
 
+struct ipr_inquiry_pageC4 {
+       u8 peri_qual_dev_type;
+       u8 page_code;
+       u8 reserved1;
+       u8 len;
+       u8 cache_cap[4];
+#define IPR_CAP_SYNC_CACHE             0x08
+       u8 reserved2[20];
+} __packed;
+
 struct ipr_hostrcb_device_data_entry {
        struct ipr_vpd vpd;
        struct ipr_res_addr dev_res_addr;
@@ -1319,6 +1336,7 @@ struct ipr_misc_cbs {
        struct ipr_inquiry_page0 page0_data;
        struct ipr_inquiry_page3 page3_data;
        struct ipr_inquiry_cap cap;
+       struct ipr_inquiry_pageC4 pageC4_data;
        struct ipr_mode_pages mode_pages;
        struct ipr_supported_device supp_dev;
 };
index 0dfcabe3ca7c2c7862b3712a391f2cd4ba19015a..77128d680e3bc615732767ea428292c93ffb32fa 100644 (file)
@@ -170,7 +170,6 @@ static struct scsi_host_template isci_sht = {
        .target_destroy                 = sas_target_destroy,
        .ioctl                          = sas_ioctl,
        .shost_attrs                    = isci_host_attrs,
-       .use_blk_tags                   = 1,
        .track_queue_depth              = 1,
 };
 
@@ -272,11 +271,11 @@ static void isci_unregister(struct isci_host *isci_host)
        if (!isci_host)
                return;
 
+       shost = to_shost(isci_host);
+       scsi_remove_host(shost);
        sas_unregister_ha(&isci_host->sas_ha);
 
-       shost = to_shost(isci_host);
        sas_remove_host(shost);
-       scsi_remove_host(shost);
        scsi_host_put(shost);
 }
 
index 9fbf78ed821b3ceeb36a941e5fddd3142d0300cf..c168321b560e2d2046eec8299b3574abc90a90df 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/export.h>
 
 /**
- * fc_vport_create() - Create a new NPIV vport instance
+ * libfc_vport_create() - Create a new NPIV vport instance
  * @vport: fc_vport structure from scsi_transport_fc
  * @privsize: driver private data size to allocate along with the Scsi_Host
  */
index 3feeb447b7409e560eed9bbac571a41352cf6406..b6fa257ea3e0ba802e65f57d46c45944318bef7b 100644 (file)
@@ -5173,7 +5173,6 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                rjt_err = LSRJT_CMD_UNSUPPORTED;
                goto rjt;
        }
-       lcb_context = kmalloc(sizeof(struct lpfc_lcb_context), GFP_KERNEL);
 
        if (phba->hba_flag & HBA_FCOE_MODE) {
                rjt_err = LSRJT_CMD_UNSUPPORTED;
@@ -5204,6 +5203,12 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                goto rjt;
        }
 
+       lcb_context = kmalloc(sizeof(*lcb_context), GFP_KERNEL);
+       if (!lcb_context) {
+               rjt_err = LSRJT_UNABLE_TPC;
+               goto rjt;
+       }
+
        state = (beacon->lcb_sub_command == LPFC_LCB_ON) ? 1 : 0;
        lcb_context->sub_command = beacon->lcb_sub_command;
        lcb_context->type = beacon->lcb_type;
@@ -5214,6 +5219,7 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        if (lpfc_sli4_set_beacon(vport, lcb_context, state)) {
                lpfc_printf_vlog(ndlp->vport, KERN_ERR,
                                 LOG_ELS, "0193 failed to send mail box");
+               kfree(lcb_context);
                lpfc_nlp_put(ndlp);
                rjt_err = LSRJT_UNABLE_TPC;
                goto rjt;
index 051b3b3bd625dea5891266a725ca514f8a98239b..4679ed4444a737e906342473031397b2137443ff 100644 (file)
@@ -5914,7 +5914,6 @@ struct scsi_host_template lpfc_template_s3 = {
        .max_sectors            = 0xFFFF,
        .vendor_id              = LPFC_NL_VENDOR_ID,
        .change_queue_depth     = scsi_change_queue_depth,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -5940,7 +5939,6 @@ struct scsi_host_template lpfc_template = {
        .max_sectors            = 0xFFFF,
        .vendor_id              = LPFC_NL_VENDOR_ID,
        .change_queue_depth     = scsi_change_queue_depth,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -5964,6 +5962,5 @@ struct scsi_host_template lpfc_vport_template = {
        .shost_attrs            = lpfc_vport_attrs,
        .max_sectors            = 0xFFFF,
        .change_queue_depth     = scsi_change_queue_depth,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
index 20c37541963f4acd04ed6836647469f3d46cdabe..c0f7c8ce54aa08b668694b4b70e19076ec72dbff 100644 (file)
@@ -35,8 +35,8 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "06.807.10.00-rc1"
-#define MEGASAS_RELDATE                                "March 6, 2015"
+#define MEGASAS_VERSION                                "06.808.16.00-rc1"
+#define MEGASAS_RELDATE                                "Oct. 8, 2015"
 
 /*
  * Device IDs
 #define PCI_DEVICE_ID_LSI_PLASMA               0x002f
 #define PCI_DEVICE_ID_LSI_INVADER              0x005d
 #define PCI_DEVICE_ID_LSI_FURY                 0x005f
+#define PCI_DEVICE_ID_LSI_INTRUDER             0x00ce
+#define PCI_DEVICE_ID_LSI_INTRUDER_24          0x00cf
+#define PCI_DEVICE_ID_LSI_CUTLASS_52           0x0052
+#define PCI_DEVICE_ID_LSI_CUTLASS_53           0x0053
 
 /*
  * Intel HBA SSDIDs
 #define MEGARAID_INTEL_RS3MC044_SSDID          0x9381
 #define MEGARAID_INTEL_RS3WC080_SSDID          0x9341
 #define MEGARAID_INTEL_RS3WC040_SSDID          0x9343
+#define MEGARAID_INTEL_RMS3BC160_SSDID         0x352B
+
+/*
+ * Intruder HBA SSDIDs
+ */
+#define MEGARAID_INTRUDER_SSDID1               0x9371
+#define MEGARAID_INTRUDER_SSDID2               0x9390
+#define MEGARAID_INTRUDER_SSDID3               0x9370
 
 /*
  * Intel HBA branding
@@ -78,6 +90,8 @@
        "Intel(R) RAID Controller RS3WC080"
 #define MEGARAID_INTEL_RS3WC040_BRANDING       \
        "Intel(R) RAID Controller RS3WC040"
+#define MEGARAID_INTEL_RMS3BC160_BRANDING      \
+       "Intel(R) Integrated RAID Module RMS3BC160"
 
 /*
  * =====================================
@@ -273,6 +287,16 @@ enum MFI_STAT {
        MFI_STAT_INVALID_STATUS = 0xFF
 };
 
+enum mfi_evt_class {
+       MFI_EVT_CLASS_DEBUG =           -2,
+       MFI_EVT_CLASS_PROGRESS =        -1,
+       MFI_EVT_CLASS_INFO =            0,
+       MFI_EVT_CLASS_WARNING =         1,
+       MFI_EVT_CLASS_CRITICAL =        2,
+       MFI_EVT_CLASS_FATAL =           3,
+       MFI_EVT_CLASS_DEAD =            4
+};
+
 /*
  * Crash dump related defines
  */
@@ -364,6 +388,8 @@ enum MR_EVT_ARGS {
        MR_EVT_ARGS_GENERIC,
 };
 
+
+#define SGE_BUFFER_SIZE        4096
 /*
  * define constants for device list query options
  */
@@ -394,6 +420,7 @@ enum MR_LD_QUERY_TYPE {
 #define MR_EVT_FOREIGN_CFG_IMPORTED                     0x00db
 #define MR_EVT_LD_OFFLINE                               0x00fc
 #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED             0x0152
+#define MR_EVT_CTRL_PROP_CHANGED                       0x012f
 
 enum MR_PD_STATE {
        MR_PD_STATE_UNCONFIGURED_GOOD   = 0x00,
@@ -973,7 +1000,12 @@ struct megasas_ctrl_info {
 
        struct {
 #if defined(__BIG_ENDIAN_BITFIELD)
-               u32     reserved:12;
+               u32     reserved:7;
+               u32     useSeqNumJbodFP:1;
+               u32     supportExtendedSSCSize:1;
+               u32     supportDiskCacheSettingForSysPDs:1;
+               u32     supportCPLDUpdate:1;
+               u32     supportTTYLogCompression:1;
                u32     discardCacheDuringLDDelete:1;
                u32     supportSecurityonJBOD:1;
                u32     supportCacheBypassModes:1;
@@ -1013,7 +1045,12 @@ struct megasas_ctrl_info {
                u32     supportCacheBypassModes:1;
                u32     supportSecurityonJBOD:1;
                u32     discardCacheDuringLDDelete:1;
-               u32     reserved:12;
+               u32     supportTTYLogCompression:1;
+               u32     supportCPLDUpdate:1;
+               u32     supportDiskCacheSettingForSysPDs:1;
+               u32     supportExtendedSSCSize:1;
+               u32     useSeqNumJbodFP:1;
+               u32     reserved:7;
 #endif
        } adapterOperations3;
 
@@ -1229,7 +1266,9 @@ union megasas_sgl_frame {
 typedef union _MFI_CAPABILITIES {
        struct {
 #if   defined(__BIG_ENDIAN_BITFIELD)
-               u32     reserved:25;
+               u32     reserved:23;
+               u32     support_ext_io_size:1;
+               u32     support_ext_queue_depth:1;
                u32     security_protocol_cmds_fw:1;
                u32     support_core_affinity:1;
                u32     support_ndrive_r1_lb:1;
@@ -1245,7 +1284,9 @@ typedef union _MFI_CAPABILITIES {
                u32     support_ndrive_r1_lb:1;
                u32     support_core_affinity:1;
                u32     security_protocol_cmds_fw:1;
-               u32     reserved:25;
+               u32     support_ext_queue_depth:1;
+               u32     support_ext_io_size:1;
+               u32     reserved:23;
 #endif
        } mfi_capabilities;
        __le32          reg;
@@ -1690,6 +1731,7 @@ struct megasas_instance {
        u32 crash_dump_drv_support;
        u32 crash_dump_app_support;
        u32 secure_jbod_support;
+       bool use_seqnum_jbod_fp;   /* Added for PD sequence */
        spinlock_t crashdump_lock;
 
        struct megasas_register_set __iomem *reg_set;
@@ -1748,6 +1790,7 @@ struct megasas_instance {
        u8 UnevenSpanSupport;
 
        u8 supportmax256vd;
+       u8 allow_fw_scan;
        u16 fw_supported_vd_count;
        u16 fw_supported_pd_count;
 
@@ -1769,7 +1812,9 @@ struct megasas_instance {
        struct msix_entry msixentry[MEGASAS_MAX_MSIX_QUEUES];
        struct megasas_irq_context irq_context[MEGASAS_MAX_MSIX_QUEUES];
        u64 map_id;
+       u64 pd_seq_map_id;
        struct megasas_cmd *map_update_cmd;
+       struct megasas_cmd *jbod_seq_cmd;
        unsigned long bar;
        long reset_flags;
        struct mutex reset_mutex;
@@ -1780,6 +1825,7 @@ struct megasas_instance {
        char mpio;
        u16 throttlequeuedepth;
        u8 mask_interrupts;
+       u16 max_chain_frame_sz;
        u8 is_imr;
        bool dev_handle;
 };
@@ -1985,6 +2031,9 @@ __le16 get_updated_dev_handle(struct megasas_instance *instance,
 void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
        struct LD_LOAD_BALANCE_INFO *lbInfo);
 int megasas_get_ctrl_info(struct megasas_instance *instance);
+/* PD sequence */
+int
+megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend);
 int megasas_set_crash_dump_params(struct megasas_instance *instance,
        u8 crash_buf_state);
 void megasas_free_host_crash_buffer(struct megasas_instance *instance);
@@ -2000,5 +2049,6 @@ void __megasas_return_cmd(struct megasas_instance *instance,
 void megasas_return_mfi_mpt_pthr(struct megasas_instance *instance,
        struct megasas_cmd *cmd_mfi, struct megasas_cmd_fusion *cmd_fusion);
 int megasas_cmd_type(struct scsi_cmnd *cmd);
+void megasas_setup_jbod_map(struct megasas_instance *instance);
 
 #endif                         /*LSI_MEGARAID_SAS_H */
index eaa81e552fd26f715122da4ee5e38427bb4ddb72..97a1c1c33b05dd2ba7e2dfe4feb3469dce3b6199 100644 (file)
@@ -135,6 +135,12 @@ static struct pci_device_id megasas_pci_table[] = {
        /* Invader */
        {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FURY)},
        /* Fury */
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER)},
+       /* Intruder */
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_INTRUDER_24)},
+       /* Intruder 24 port*/
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_52)},
+       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_CUTLASS_53)},
        {}
 };
 
@@ -260,6 +266,66 @@ megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
 
 }
 
+static const char *
+format_timestamp(uint32_t timestamp)
+{
+       static char buffer[32];
+
+       if ((timestamp & 0xff000000) == 0xff000000)
+               snprintf(buffer, sizeof(buffer), "boot + %us", timestamp &
+               0x00ffffff);
+       else
+               snprintf(buffer, sizeof(buffer), "%us", timestamp);
+       return buffer;
+}
+
+static const char *
+format_class(int8_t class)
+{
+       static char buffer[6];
+
+       switch (class) {
+       case MFI_EVT_CLASS_DEBUG:
+               return "debug";
+       case MFI_EVT_CLASS_PROGRESS:
+               return "progress";
+       case MFI_EVT_CLASS_INFO:
+               return "info";
+       case MFI_EVT_CLASS_WARNING:
+               return "WARN";
+       case MFI_EVT_CLASS_CRITICAL:
+               return "CRIT";
+       case MFI_EVT_CLASS_FATAL:
+               return "FATAL";
+       case MFI_EVT_CLASS_DEAD:
+               return "DEAD";
+       default:
+               snprintf(buffer, sizeof(buffer), "%d", class);
+               return buffer;
+       }
+}
+
+/**
+  * megasas_decode_evt: Decode FW AEN event and print critical event
+  * for information.
+  * @instance:                 Adapter soft state
+  */
+static void
+megasas_decode_evt(struct megasas_instance *instance)
+{
+       struct megasas_evt_detail *evt_detail = instance->evt_detail;
+       union megasas_evt_class_locale class_locale;
+       class_locale.word = le32_to_cpu(evt_detail->cl.word);
+
+       if (class_locale.members.class >= MFI_EVT_CLASS_CRITICAL)
+               dev_info(&instance->pdev->dev, "%d (%s/0x%04x/%s) - %s\n",
+                       le32_to_cpu(evt_detail->seq_num),
+                       format_timestamp(le32_to_cpu(evt_detail->time_stamp)),
+                       (class_locale.members.locale),
+                       format_class(class_locale.members.class),
+                       evt_detail->description);
+}
+
 /**
 *      The following functions are defined for xscale
 *      (deviceid : 1064R, PERC5) controllers
@@ -1659,8 +1725,56 @@ static struct megasas_instance *megasas_lookup_instance(u16 host_no)
        return NULL;
 }
 
+/*
+* megasas_set_dma_alignment - Set DMA alignment for PI enabled VD
+*
+* @sdev: OS provided scsi device
+*
+* Returns void
+*/
+static void megasas_set_dma_alignment(struct scsi_device *sdev)
+{
+       u32 device_id, ld;
+       struct megasas_instance *instance;
+       struct fusion_context *fusion;
+       struct MR_LD_RAID *raid;
+       struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
+
+       instance = megasas_lookup_instance(sdev->host->host_no);
+       fusion = instance->ctrl_context;
+
+       if (!fusion)
+               return;
+
+       if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) {
+               device_id = ((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL)
+                                       + sdev->id;
+               local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
+               ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
+               raid = MR_LdRaidGet(ld, local_map_ptr);
+
+               if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER)
+                       blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
+       }
+}
+
 static int megasas_slave_configure(struct scsi_device *sdev)
 {
+       u16 pd_index = 0;
+       struct megasas_instance *instance;
+
+       instance = megasas_lookup_instance(sdev->host->host_no);
+       if (instance->allow_fw_scan) {
+               if (sdev->channel < MEGASAS_MAX_PD_CHANNELS &&
+                       sdev->type == TYPE_DISK) {
+                       pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
+                               sdev->id;
+                       if (instance->pd_list[pd_index].driveState !=
+                               MR_PD_STATE_SYSTEM)
+                               return -ENXIO;
+               }
+       }
+       megasas_set_dma_alignment(sdev);
        /*
         * The RAID firmware may require extended timeouts.
         */
@@ -1683,8 +1797,8 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
                pd_index =
                        (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
                        sdev->id;
-               if (instance->pd_list[pd_index].driveState ==
-                                       MR_PD_STATE_SYSTEM) {
+               if ((instance->allow_fw_scan || instance->pd_list[pd_index].driveState ==
+                       MR_PD_STATE_SYSTEM)) {
                        return 0;
                }
                return -ENXIO;
@@ -1736,10 +1850,7 @@ void megaraid_sas_kill_hba(struct megasas_instance *instance)
        msleep(1000);
        if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
                (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+               (instance->ctrl_context)) {
                writel(MFI_STOP_ADP, &instance->reg_set->doorbell);
                /* Flush */
                readl(&instance->reg_set->doorbell);
@@ -2506,10 +2617,7 @@ static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
        /*
         * First wait for all commands to complete
         */
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+       if (instance->ctrl_context)
                ret = megasas_reset_fusion(scmd->device->host, 1);
        else
                ret = megasas_generic_reset(scmd);
@@ -2837,7 +2945,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
        struct megasas_header *hdr = &cmd->frame->hdr;
        unsigned long flags;
        struct fusion_context *fusion = instance->ctrl_context;
-       u32 opcode;
+       u32 opcode, status;
 
        /* flag for the retry reset */
        cmd->retry_for_fw_reset = 0;
@@ -2945,6 +3053,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                        && (cmd->frame->dcmd.mbox.b[1] == 1)) {
                        fusion->fast_path_io = 0;
                        spin_lock_irqsave(instance->host->host_lock, flags);
+                       instance->map_update_cmd = NULL;
                        if (cmd->frame->hdr.cmd_status != 0) {
                                if (cmd->frame->hdr.cmd_status !=
                                    MFI_STAT_NOT_FOUND)
@@ -2982,6 +3091,27 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
                        spin_unlock_irqrestore(&poll_aen_lock, flags);
                }
 
+               /* FW has an updated PD sequence */
+               if ((opcode == MR_DCMD_SYSTEM_PD_MAP_GET_INFO) &&
+                       (cmd->frame->dcmd.mbox.b[0] == 1)) {
+
+                       spin_lock_irqsave(instance->host->host_lock, flags);
+                       status = cmd->frame->hdr.cmd_status;
+                       instance->jbod_seq_cmd = NULL;
+                       megasas_return_cmd(instance, cmd);
+
+                       if (status == MFI_STAT_OK) {
+                               instance->pd_seq_map_id++;
+                               /* Re-register a pd sync seq num cmd */
+                               if (megasas_sync_pd_seq_num(instance, true))
+                                       instance->use_seqnum_jbod_fp = false;
+                       } else
+                               instance->use_seqnum_jbod_fp = false;
+
+                       spin_unlock_irqrestore(instance->host->host_lock, flags);
+                       break;
+               }
+
                /*
                 * See if got an event notification
                 */
@@ -3348,22 +3478,14 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
                                PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
                                (instance->pdev->device ==
                                 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_FUSION) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_PLASMA) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_INVADER) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_FURY)) {
+                               (instance->ctrl_context))
                                writel(
                                  MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
                                  &instance->reg_set->doorbell);
-                       } else {
+                       else
                                writel(
                                    MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
                                        &instance->reg_set->inbound_doorbell);
-                       }
 
                        max_wait = MEGASAS_RESET_WAIT_TIME;
                        cur_state = MFI_STATE_WAIT_HANDSHAKE;
@@ -3374,17 +3496,10 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
                             PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
                                (instance->pdev->device ==
                                 PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
-                           (instance->pdev->device ==
-                            PCI_DEVICE_ID_LSI_FUSION) ||
-                           (instance->pdev->device ==
-                            PCI_DEVICE_ID_LSI_PLASMA) ||
-                           (instance->pdev->device ==
-                            PCI_DEVICE_ID_LSI_INVADER) ||
-                           (instance->pdev->device ==
-                            PCI_DEVICE_ID_LSI_FURY)) {
+                               (instance->ctrl_context))
                                writel(MFI_INIT_HOTPLUG,
                                       &instance->reg_set->doorbell);
-                       else
+                       else
                                writel(MFI_INIT_HOTPLUG,
                                        &instance->reg_set->inbound_doorbell);
 
@@ -3401,24 +3516,11 @@ megasas_transition_to_ready(struct megasas_instance *instance, int ocr)
                                PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
                                (instance->pdev->device ==
                                PCI_DEVICE_ID_LSI_SAS0071SKINNY)  ||
-                               (instance->pdev->device
-                                       == PCI_DEVICE_ID_LSI_FUSION) ||
-                               (instance->pdev->device
-                                       == PCI_DEVICE_ID_LSI_PLASMA) ||
-                               (instance->pdev->device
-                                       == PCI_DEVICE_ID_LSI_INVADER) ||
-                               (instance->pdev->device
-                                       == PCI_DEVICE_ID_LSI_FURY)) {
+                               (instance->ctrl_context)) {
                                writel(MFI_RESET_FLAGS,
                                        &instance->reg_set->doorbell);
-                               if ((instance->pdev->device ==
-                                       PCI_DEVICE_ID_LSI_FUSION) ||
-                                       (instance->pdev->device ==
-                                       PCI_DEVICE_ID_LSI_PLASMA) ||
-                                       (instance->pdev->device ==
-                                       PCI_DEVICE_ID_LSI_INVADER) ||
-                                       (instance->pdev->device ==
-                                       PCI_DEVICE_ID_LSI_FURY)) {
+
+                               if (instance->ctrl_context) {
                                        for (i = 0; i < (10 * 1000); i += 20) {
                                                if (readl(
                                                            &instance->
@@ -3639,11 +3741,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance)
                memset(cmd->frame, 0, total_sz);
                cmd->frame->io.context = cpu_to_le32(cmd->index);
                cmd->frame->io.pad_0 = 0;
-               if ((instance->pdev->device != PCI_DEVICE_ID_LSI_FUSION) &&
-                   (instance->pdev->device != PCI_DEVICE_ID_LSI_PLASMA) &&
-                   (instance->pdev->device != PCI_DEVICE_ID_LSI_INVADER) &&
-                       (instance->pdev->device != PCI_DEVICE_ID_LSI_FURY) &&
-                   (reset_devices))
+               if (!instance->ctrl_context && reset_devices)
                        cmd->frame->hdr.cmd = MFI_CMD_INVALID;
        }
 
@@ -4136,11 +4234,21 @@ megasas_get_ctrl_info(struct megasas_instance *instance)
                le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
                le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
                megasas_update_ext_vd_details(instance);
+               instance->use_seqnum_jbod_fp =
+                       ctrl_info->adapterOperations3.useSeqNumJbodFP;
                instance->is_imr = (ctrl_info->memory_size ? 0 : 1);
                dev_info(&instance->pdev->dev,
                                "controller type\t: %s(%dMB)\n",
                                instance->is_imr ? "iMR" : "MR",
                                le16_to_cpu(ctrl_info->memory_size));
+               instance->disableOnlineCtrlReset =
+                       ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
+               dev_info(&instance->pdev->dev, "Online Controller Reset(OCR)\t: %s\n",
+                       instance->disableOnlineCtrlReset ? "Disabled" : "Enabled");
+               instance->secure_jbod_support =
+                       ctrl_info->adapterOperations3.supportSecurityonJBOD;
+               dev_info(&instance->pdev->dev, "Secure JBOD support\t: %s\n",
+                       instance->secure_jbod_support ? "Yes" : "No");
        }
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
@@ -4480,6 +4588,62 @@ megasas_destroy_irqs(struct megasas_instance *instance) {
                free_irq(instance->pdev->irq, &instance->irq_context[0]);
 }
 
+/**
+ * megasas_setup_jbod_map -    setup jbod map for FP seq_number.
+ * @instance:                          Adapter soft state
+ * @is_probe:                          Driver probe check
+ *
+ * Return 0 on success.
+ */
+void
+megasas_setup_jbod_map(struct megasas_instance *instance)
+{
+       int i;
+       struct fusion_context *fusion = instance->ctrl_context;
+       u32 pd_seq_map_sz;
+
+       pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+               (sizeof(struct MR_PD_CFG_SEQ) * (MAX_PHYSICAL_DEVICES - 1));
+
+       if (reset_devices || !fusion ||
+               !instance->ctrl_info->adapterOperations3.useSeqNumJbodFP) {
+               dev_info(&instance->pdev->dev,
+                       "Jbod map is not supported %s %d\n",
+                       __func__, __LINE__);
+               instance->use_seqnum_jbod_fp = false;
+               return;
+       }
+
+       if (fusion->pd_seq_sync[0])
+               goto skip_alloc;
+
+       for (i = 0; i < JBOD_MAPS_COUNT; i++) {
+               fusion->pd_seq_sync[i] = dma_alloc_coherent
+                       (&instance->pdev->dev, pd_seq_map_sz,
+                       &fusion->pd_seq_phys[i], GFP_KERNEL);
+               if (!fusion->pd_seq_sync[i]) {
+                       dev_err(&instance->pdev->dev,
+                               "Failed to allocate memory from %s %d\n",
+                               __func__, __LINE__);
+                       if (i == 1) {
+                               dma_free_coherent(&instance->pdev->dev,
+                                       pd_seq_map_sz, fusion->pd_seq_sync[0],
+                                       fusion->pd_seq_phys[0]);
+                               fusion->pd_seq_sync[0] = NULL;
+                       }
+                       instance->use_seqnum_jbod_fp = false;
+                       return;
+               }
+       }
+
+skip_alloc:
+       if (!megasas_sync_pd_seq_num(instance, false) &&
+               !megasas_sync_pd_seq_num(instance, true))
+               instance->use_seqnum_jbod_fp = true;
+       else
+               instance->use_seqnum_jbod_fp = false;
+}
+
 /**
  * megasas_init_fw -   Initializes the FW
  * @instance:          Adapter soft state
@@ -4498,6 +4662,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
        unsigned long bar_list;
        int i, loop, fw_msix_count = 0;
        struct IOV_111 *iovPtr;
+       struct fusion_context *fusion;
+
+       fusion = instance->ctrl_context;
 
        /* Find first memory bar */
        bar_list = pci_select_bars(instance->pdev, IORESOURCE_MEM);
@@ -4523,6 +4690,10 @@ static int megasas_init_fw(struct megasas_instance *instance)
        case PCI_DEVICE_ID_LSI_PLASMA:
        case PCI_DEVICE_ID_LSI_INVADER:
        case PCI_DEVICE_ID_LSI_FURY:
+       case PCI_DEVICE_ID_LSI_INTRUDER:
+       case PCI_DEVICE_ID_LSI_INTRUDER_24:
+       case PCI_DEVICE_ID_LSI_CUTLASS_52:
+       case PCI_DEVICE_ID_LSI_CUTLASS_53:
                instance->instancet = &megasas_instance_template_fusion;
                break;
        case PCI_DEVICE_ID_LSI_SAS1078R:
@@ -4541,6 +4712,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
        case PCI_DEVICE_ID_DELL_PERC5:
        default:
                instance->instancet = &megasas_instance_template_xscale;
+               instance->allow_fw_scan = 1;
                break;
        }
 
@@ -4575,37 +4747,32 @@ static int megasas_init_fw(struct megasas_instance *instance)
                scratch_pad_2 = readl
                        (&instance->reg_set->outbound_scratch_pad_2);
                /* Check max MSI-X vectors */
-               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-                   (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA)) {
-                       instance->msix_vectors = (scratch_pad_2
-                               & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
-                       fw_msix_count = instance->msix_vectors;
-                       if (msix_vectors)
-                               instance->msix_vectors =
-                                       min(msix_vectors,
-                                           instance->msix_vectors);
-               } else if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER)
-                       || (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
-                       /* Invader/Fury supports more than 8 MSI-X */
-                       instance->msix_vectors = ((scratch_pad_2
-                               & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
-                               >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
-                       fw_msix_count = instance->msix_vectors;
-                       /* Save 1-15 reply post index address to local memory
-                        * Index 0 is already saved from reg offset
-                        * MPI2_REPLY_POST_HOST_INDEX_OFFSET
-                        */
-                       for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
-                               instance->reply_post_host_index_addr[loop] =
-                                       (u32 __iomem *)
-                                       ((u8 __iomem *)instance->reg_set +
-                                       MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
-                                       + (loop * 0x10));
+               if (fusion) {
+                       if (fusion->adapter_type == THUNDERBOLT_SERIES) { /* Thunderbolt Series*/
+                               instance->msix_vectors = (scratch_pad_2
+                                       & MR_MAX_REPLY_QUEUES_OFFSET) + 1;
+                               fw_msix_count = instance->msix_vectors;
+                       } else { /* Invader series supports more than 8 MSI-x vectors*/
+                               instance->msix_vectors = ((scratch_pad_2
+                                       & MR_MAX_REPLY_QUEUES_EXT_OFFSET)
+                                       >> MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT) + 1;
+                               fw_msix_count = instance->msix_vectors;
+                               /* Save 1-15 reply post index address to local memory
+                                * Index 0 is already saved from reg offset
+                                * MPI2_REPLY_POST_HOST_INDEX_OFFSET
+                                */
+                               for (loop = 1; loop < MR_MAX_MSIX_REG_ARRAY; loop++) {
+                                       instance->reply_post_host_index_addr[loop] =
+                                               (u32 __iomem *)
+                                               ((u8 __iomem *)instance->reg_set +
+                                               MPI2_SUP_REPLY_POST_HOST_INDEX_OFFSET
+                                               + (loop * 0x10));
+                               }
                        }
                        if (msix_vectors)
                                instance->msix_vectors = min(msix_vectors,
                                        instance->msix_vectors);
-               } else
+               } else /* MFI adapters */
                        instance->msix_vectors = 1;
                /* Don't bother allocating more MSI-X vectors than cpus */
                instance->msix_vectors = min(instance->msix_vectors,
@@ -4626,6 +4793,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
                "current msix/online cpus\t: (%d/%d)\n",
                instance->msix_vectors, (unsigned int)num_online_cpus());
 
+       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
+               (unsigned long)instance);
+
        if (instance->msix_vectors ?
                megasas_setup_irqs_msix(instance, 1) :
                megasas_setup_irqs_ioapic(instance))
@@ -4646,13 +4816,13 @@ static int megasas_init_fw(struct megasas_instance *instance)
        if (instance->instancet->init_adapter(instance))
                goto fail_init_adapter;
 
-       tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
-               (unsigned long)instance);
 
        instance->instancet->enable_intr(instance);
 
        dev_err(&instance->pdev->dev, "INIT adapter done\n");
 
+       megasas_setup_jbod_map(instance);
+
        /** for passthrough
         * the following function will get the PD LIST.
         */
@@ -4686,8 +4856,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
        tmp_sectors = min_t(u32, max_sectors_1, max_sectors_2);
 
-       instance->disableOnlineCtrlReset =
-       ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
        instance->mpio = ctrl_info->adapterOperations2.mpio;
        instance->UnevenSpanSupport =
                ctrl_info->adapterOperations2.supportUnevenSpans;
@@ -4700,18 +4868,22 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
        }
        if (ctrl_info->host_interface.SRIOV) {
-               if (!ctrl_info->adapterOperations2.activePassive)
-                       instance->PlasmaFW111 = 1;
-
-               if (!instance->PlasmaFW111)
-                       instance->requestorId =
-                               ctrl_info->iov.requestorId;
-               else {
-                       iovPtr = (struct IOV_111 *)((unsigned char *)ctrl_info + IOV_111_OFFSET);
-                       instance->requestorId = iovPtr->requestorId;
+               instance->requestorId = ctrl_info->iov.requestorId;
+               if (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) {
+                       if (!ctrl_info->adapterOperations2.activePassive)
+                           instance->PlasmaFW111 = 1;
+
+                       dev_info(&instance->pdev->dev, "SR-IOV: firmware type: %s\n",
+                           instance->PlasmaFW111 ? "1.11" : "new");
+
+                       if (instance->PlasmaFW111) {
+                           iovPtr = (struct IOV_111 *)
+                               ((unsigned char *)ctrl_info + IOV_111_OFFSET);
+                           instance->requestorId = iovPtr->requestorId;
+                       }
                }
-               dev_warn(&instance->pdev->dev, "I am VF "
-                      "requestorId %d\n", instance->requestorId);
+               dev_info(&instance->pdev->dev, "SRIOV: VF requestorId %d\n",
+                       instance->requestorId);
        }
 
        instance->crash_dump_fw_support =
@@ -4732,8 +4904,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
                instance->crash_dump_buf = NULL;
        }
 
-       instance->secure_jbod_support =
-               ctrl_info->adapterOperations3.supportSecurityonJBOD;
 
        dev_info(&instance->pdev->dev,
                "pci id\t\t: (0x%04x)/(0x%04x)/(0x%04x)/(0x%04x)\n",
@@ -4743,16 +4913,14 @@ static int megasas_init_fw(struct megasas_instance *instance)
                le16_to_cpu(ctrl_info->pci.sub_device_id));
        dev_info(&instance->pdev->dev, "unevenspan support      : %s\n",
                instance->UnevenSpanSupport ? "yes" : "no");
-       dev_info(&instance->pdev->dev, "disable ocr             : %s\n",
-               instance->disableOnlineCtrlReset ? "yes" : "no");
        dev_info(&instance->pdev->dev, "firmware crash dump     : %s\n",
                instance->crash_dump_drv_support ? "yes" : "no");
-       dev_info(&instance->pdev->dev, "secure jbod             : %s\n",
-               instance->secure_jbod_support ? "yes" : "no");
+       dev_info(&instance->pdev->dev, "jbod sync map           : %s\n",
+               instance->use_seqnum_jbod_fp ? "yes" : "no");
 
 
        instance->max_sectors_per_req = instance->max_num_sge *
-                                               PAGE_SIZE / 512;
+                                               SGE_BUFFER_SIZE / 512;
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
@@ -5049,7 +5217,6 @@ static int megasas_start_aen(struct megasas_instance *instance)
 static int megasas_io_attach(struct megasas_instance *instance)
 {
        struct Scsi_Host *host = instance->host;
-       u32 error;
 
        /*
         * Export parameters required by SCSI mid-layer
@@ -5092,20 +5259,10 @@ static int megasas_io_attach(struct megasas_instance *instance)
        host->max_cmd_len = 16;
 
        /* Fusion only supports host reset */
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+       if (instance->ctrl_context) {
                host->hostt->eh_device_reset_handler = NULL;
                host->hostt->eh_bus_reset_handler = NULL;
        }
-       error = scsi_init_shared_tag_map(host, host->can_queue);
-       if (error) {
-               dev_err(&instance->pdev->dev,
-                       "Failed to shared tag from %s %d\n",
-                       __func__, __LINE__);
-               return -ENODEV;
-       }
 
        /*
         * Notify the mid-layer about the new controller
@@ -5218,6 +5375,10 @@ static int megasas_probe_one(struct pci_dev *pdev,
        case PCI_DEVICE_ID_LSI_PLASMA:
        case PCI_DEVICE_ID_LSI_INVADER:
        case PCI_DEVICE_ID_LSI_FURY:
+       case PCI_DEVICE_ID_LSI_INTRUDER:
+       case PCI_DEVICE_ID_LSI_INTRUDER_24:
+       case PCI_DEVICE_ID_LSI_CUTLASS_52:
+       case PCI_DEVICE_ID_LSI_CUTLASS_53:
        {
                instance->ctrl_context_pages =
                        get_order(sizeof(struct fusion_context));
@@ -5231,6 +5392,11 @@ static int megasas_probe_one(struct pci_dev *pdev,
                fusion = instance->ctrl_context;
                memset(fusion, 0,
                        ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
+               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
+                       (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA))
+                       fusion->adapter_type = THUNDERBOLT_SERIES;
+               else
+                       fusion->adapter_type = INVADER_SERIES;
        }
        break;
        default: /* For all other supported controllers */
@@ -5333,10 +5499,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
        instance->disableOnlineCtrlReset = 1;
        instance->UnevenSpanSupport = 0;
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+       if (instance->ctrl_context) {
                INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq);
                INIT_WORK(&instance->crash_init, megasas_fusion_crash_dump_wq);
        } else
@@ -5416,10 +5579,7 @@ static int megasas_probe_one(struct pci_dev *pdev,
        instance->instancet->disable_intr(instance);
        megasas_destroy_irqs(instance);
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_PLASMA) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-           (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+       if (instance->ctrl_context)
                megasas_release_fusion(instance);
        else
                megasas_release_mfi(instance);
@@ -5506,10 +5666,14 @@ static void megasas_shutdown_controller(struct megasas_instance *instance,
 
        if (instance->aen_cmd)
                megasas_issue_blocked_abort_cmd(instance,
-                       instance->aen_cmd, 30);
+                       instance->aen_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
        if (instance->map_update_cmd)
                megasas_issue_blocked_abort_cmd(instance,
-                       instance->map_update_cmd, 30);
+                       instance->map_update_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
+       if (instance->jbod_seq_cmd)
+               megasas_issue_blocked_abort_cmd(instance,
+                       instance->jbod_seq_cmd, MEGASAS_BLOCKED_CMD_TIMEOUT);
+
        dcmd = &cmd->frame->dcmd;
 
        memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
@@ -5628,12 +5792,7 @@ megasas_resume(struct pci_dev *pdev)
                                  instance->msix_vectors))
                goto fail_reenable_msix;
 
-       switch (instance->pdev->device) {
-       case PCI_DEVICE_ID_LSI_FUSION:
-       case PCI_DEVICE_ID_LSI_PLASMA:
-       case PCI_DEVICE_ID_LSI_INVADER:
-       case PCI_DEVICE_ID_LSI_FURY:
-       {
+       if (instance->ctrl_context) {
                megasas_reset_reply_desc(instance);
                if (megasas_ioc_init_fusion(instance)) {
                        megasas_free_cmds(instance);
@@ -5642,14 +5801,11 @@ megasas_resume(struct pci_dev *pdev)
                }
                if (!megasas_get_map_info(instance))
                        megasas_sync_map_info(instance);
-       }
-       break;
-       default:
+       } else {
                *instance->producer = 0;
                *instance->consumer = 0;
                if (megasas_issue_init_mfi(instance))
                        goto fail_init_mfi;
-               break;
        }
 
        tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
@@ -5674,6 +5830,7 @@ megasas_resume(struct pci_dev *pdev)
        }
 
        instance->instancet->enable_intr(instance);
+       megasas_setup_jbod_map(instance);
        instance->unload = 0;
 
        /*
@@ -5721,6 +5878,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
        struct Scsi_Host *host;
        struct megasas_instance *instance;
        struct fusion_context *fusion;
+       u32 pd_seq_map_sz;
 
        instance = pci_get_drvdata(pdev);
        instance->unload = 1;
@@ -5769,12 +5927,11 @@ static void megasas_detach_one(struct pci_dev *pdev)
        if (instance->msix_vectors)
                pci_disable_msix(instance->pdev);
 
-       switch (instance->pdev->device) {
-       case PCI_DEVICE_ID_LSI_FUSION:
-       case PCI_DEVICE_ID_LSI_PLASMA:
-       case PCI_DEVICE_ID_LSI_INVADER:
-       case PCI_DEVICE_ID_LSI_FURY:
+       if (instance->ctrl_context) {
                megasas_release_fusion(instance);
+                       pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+                               (sizeof(struct MR_PD_CFG_SEQ) *
+                                       (MAX_PHYSICAL_DEVICES - 1));
                for (i = 0; i < 2 ; i++) {
                        if (fusion->ld_map[i])
                                dma_free_coherent(&instance->pdev->dev,
@@ -5784,11 +5941,15 @@ static void megasas_detach_one(struct pci_dev *pdev)
                        if (fusion->ld_drv_map[i])
                                free_pages((ulong)fusion->ld_drv_map[i],
                                        fusion->drv_map_pages);
+                               if (fusion->pd_seq_sync)
+                                       dma_free_coherent(&instance->pdev->dev,
+                                               pd_seq_map_sz,
+                                               fusion->pd_seq_sync[i],
+                                               fusion->pd_seq_phys[i]);
                }
                free_pages((ulong)instance->ctrl_context,
                        instance->ctrl_context_pages);
-               break;
-       default:
+       } else {
                megasas_release_mfi(instance);
                pci_free_consistent(pdev, sizeof(u32),
                                    instance->producer,
@@ -5796,7 +5957,6 @@ static void megasas_detach_one(struct pci_dev *pdev)
                pci_free_consistent(pdev, sizeof(u32),
                                    instance->consumer,
                                    instance->consumer_h);
-               break;
        }
 
        kfree(instance->ctrl_info);
@@ -6316,6 +6476,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
        int i;
        int error = 0;
        compat_uptr_t ptr;
+       unsigned long local_raw_ptr;
+       u32 local_sense_off;
+       u32 local_sense_len;
 
        if (clear_user(ioc, sizeof(*ioc)))
                return -EFAULT;
@@ -6333,9 +6496,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg)
         * sense_len is not null, so prepare the 64bit value under
         * the same condition.
         */
-       if (ioc->sense_len) {
+       if (get_user(local_raw_ptr, ioc->frame.raw) ||
+               get_user(local_sense_off, &ioc->sense_off) ||
+               get_user(local_sense_len, &ioc->sense_len))
+               return -EFAULT;
+
+
+       if (local_sense_len) {
                void __user **sense_ioc_ptr =
-                       (void __user **)(ioc->frame.raw + ioc->sense_off);
+                       (void __user **)((u8*)local_raw_ptr + local_sense_off);
                compat_uptr_t *sense_cioc_ptr =
                        (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
                if (get_user(ptr, sense_cioc_ptr) ||
@@ -6504,6 +6673,7 @@ megasas_aen_polling(struct work_struct *work)
        instance->ev = NULL;
        host = instance->host;
        if (instance->evt_detail) {
+               megasas_decode_evt(instance);
 
                switch (le32_to_cpu(instance->evt_detail->code)) {
                case MR_EVT_PD_INSERTED:
@@ -6564,8 +6734,7 @@ megasas_aen_polling(struct work_struct *work)
                case MR_EVT_CFG_CLEARED:
                case MR_EVT_LD_DELETED:
                        if (!instance->requestorId ||
-                           (instance->requestorId &&
-                            megasas_get_ld_vf_affiliation(instance, 0))) {
+                           megasas_get_ld_vf_affiliation(instance, 0)) {
                                if (megasas_ld_list_query(instance,
                                                          MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
                                        megasas_get_ld_list(instance);
@@ -6596,8 +6765,7 @@ megasas_aen_polling(struct work_struct *work)
                        break;
                case MR_EVT_LD_CREATED:
                        if (!instance->requestorId ||
-                           (instance->requestorId &&
-                            megasas_get_ld_vf_affiliation(instance, 0))) {
+                           megasas_get_ld_vf_affiliation(instance, 0)) {
                                if (megasas_ld_list_query(instance,
                                                          MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
                                        megasas_get_ld_list(instance);
@@ -6627,6 +6795,9 @@ megasas_aen_polling(struct work_struct *work)
                case MR_EVT_LD_STATE_CHANGE:
                        doscan = 1;
                        break;
+               case MR_EVT_CTRL_PROP_CHANGED:
+                       megasas_get_ctrl_info(instance);
+                       break;
                default:
                        doscan = 0;
                        break;
@@ -6663,8 +6834,7 @@ megasas_aen_polling(struct work_struct *work)
                }
 
                if (!instance->requestorId ||
-                   (instance->requestorId &&
-                    megasas_get_ld_vf_affiliation(instance, 0))) {
+                   megasas_get_ld_vf_affiliation(instance, 0)) {
                        if (megasas_ld_list_query(instance,
                                                  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
                                megasas_get_ld_list(instance);
index be57b18675a4b1b96243e067a71cd2db2a80c1c5..741509b3561776a874189ad1613984df86129ffe 100644 (file)
@@ -741,14 +741,12 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
        u8      physArm, span;
        u64     row;
        u8      retval = TRUE;
-       u8      do_invader = 0;
        u64     *pdBlock = &io_info->pdBlock;
        __le16  *pDevHandle = &io_info->devHandle;
        u32     logArm, rowMod, armQ, arm;
+       struct fusion_context *fusion;
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
-               instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
-               do_invader = 1;
+       fusion = instance->ctrl_context;
 
        /*Get row and span from io_info for Uneven Span IO.*/
        row         = io_info->start_row;
@@ -779,7 +777,8 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
        else {
                *pDevHandle = cpu_to_le16(MR_PD_INVALID);
                if ((raid->level >= 5) &&
-                       (!do_invader  || (do_invader &&
+                       ((fusion->adapter_type == THUNDERBOLT_SERIES)  ||
+                       ((fusion->adapter_type == INVADER_SERIES) &&
                        (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
                        pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
                else if (raid->level == 1) {
@@ -823,13 +822,12 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
        u8          physArm, span;
        u64         row;
        u8          retval = TRUE;
-       u8          do_invader = 0;
        u64         *pdBlock = &io_info->pdBlock;
        __le16      *pDevHandle = &io_info->devHandle;
+       struct fusion_context *fusion;
+
+       fusion = instance->ctrl_context;
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
-               instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
-               do_invader = 1;
 
        row =  mega_div64_32(stripRow, raid->rowDataSize);
 
@@ -875,7 +873,8 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
                /* set dev handle as invalid. */
                *pDevHandle = cpu_to_le16(MR_PD_INVALID);
                if ((raid->level >= 5) &&
-                       (!do_invader  || (do_invader &&
+                       ((fusion->adapter_type == THUNDERBOLT_SERIES)  ||
+                       ((fusion->adapter_type == INVADER_SERIES) &&
                        (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
                        pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
                else if (raid->level == 1) {
@@ -909,6 +908,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
                    struct RAID_CONTEXT *pRAID_Context,
                    struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN)
 {
+       struct fusion_context *fusion;
        struct MR_LD_RAID  *raid;
        u32         ld, stripSize, stripe_mask;
        u64         endLba, endStrip, endRow, start_row, start_strip;
@@ -929,6 +929,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
        isRead = io_info->isRead;
        io_info->IoforUnevenSpan = 0;
        io_info->start_span     = SPAN_INVALID;
+       fusion = instance->ctrl_context;
 
        ld = MR_TargetIdToLdGet(ldTgtId, map);
        raid = MR_LdRaidGet(ld, map);
@@ -1092,8 +1093,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
                cpu_to_le16(raid->fpIoTimeoutForLd ?
                            raid->fpIoTimeoutForLd :
                            map->raidMap.fpPdIoTimeoutSec);
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+       if (fusion->adapter_type == INVADER_SERIES)
                pRAID_Context->regLockFlags = (isRead) ?
                        raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
        else
@@ -1198,10 +1198,6 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
                                                span_row_width +=
                                                        MR_LdSpanPtrGet
                                                        (ld, count, map)->spanRowDataSize;
-                                               printk(KERN_INFO "megasas:"
-                                                       "span %x rowDataSize %x\n",
-                                                       count, MR_LdSpanPtrGet
-                                                       (ld, count, map)->spanRowDataSize);
                                        }
                                }
 
index f0837cc3b163949628cdeab58ed6073eb7015566..8d630a552b078721c5c5eea640995046a9907565 100644 (file)
@@ -316,26 +316,23 @@ static int megasas_create_frame_pool_fusion(struct megasas_instance *instance)
        u32 max_cmd;
        struct fusion_context *fusion;
        struct megasas_cmd_fusion *cmd;
-       u32 total_sz_chain_frame;
 
        fusion = instance->ctrl_context;
        max_cmd = instance->max_fw_cmds;
 
-       total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME;
 
        /*
         * Use DMA pool facility provided by PCI layer
         */
 
-       fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion",
-                                             instance->pdev,
-                                             total_sz_chain_frame, 4,
-                                             0);
+       fusion->sg_dma_pool = pci_pool_create("sg_pool_fusion", instance->pdev,
+                                               instance->max_chain_frame_sz,
+                                               4, 0);
        if (!fusion->sg_dma_pool) {
                dev_printk(KERN_DEBUG, &instance->pdev->dev, "failed to setup request pool fusion\n");
                return -ENOMEM;
        }
-       fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion",
+       fusion->sense_dma_pool = pci_pool_create("sense pool fusion",
                                                 instance->pdev,
                                                 SCSI_SENSE_BUFFERSIZE, 64, 0);
 
@@ -605,6 +602,7 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
        int i;
        struct megasas_header *frame_hdr;
        const char *sys_info;
+       MFI_CAPABILITIES *drv_ops;
 
        fusion = instance->ctrl_context;
 
@@ -652,20 +650,21 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
        init_frame->cmd = MFI_CMD_INIT;
        init_frame->cmd_status = 0xFF;
 
+       drv_ops = (MFI_CAPABILITIES *) &(init_frame->driver_operations);
+
        /* driver support Extended MSIX */
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
-               init_frame->driver_operations.
-                       mfi_capabilities.support_additional_msix = 1;
+       if (fusion->adapter_type == INVADER_SERIES)
+               drv_ops->mfi_capabilities.support_additional_msix = 1;
        /* driver supports HA / Remote LUN over Fast Path interface */
-       init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
-               = 1;
-       init_frame->driver_operations.mfi_capabilities.support_max_255lds
-               = 1;
-       init_frame->driver_operations.mfi_capabilities.support_ndrive_r1_lb
-               = 1;
-       init_frame->driver_operations.mfi_capabilities.security_protocol_cmds_fw
-               = 1;
+       drv_ops->mfi_capabilities.support_fp_remote_lun = 1;
+
+       drv_ops->mfi_capabilities.support_max_255lds = 1;
+       drv_ops->mfi_capabilities.support_ndrive_r1_lb = 1;
+       drv_ops->mfi_capabilities.security_protocol_cmds_fw = 1;
+
+       if (instance->max_chain_frame_sz > MEGASAS_CHAIN_FRAME_SZ_MIN)
+               drv_ops->mfi_capabilities.support_ext_io_size = 1;
+
        /* Convert capability to LE32 */
        cpu_to_le32s((u32 *)&init_frame->driver_operations.mfi_capabilities);
 
@@ -726,6 +725,83 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
        return ret;
 }
 
+/**
+ * megasas_sync_pd_seq_num -   JBOD SEQ MAP
+ * @instance:          Adapter soft state
+ * @pend:              set to 1, if it is pended jbod map.
+ *
+ * Issue Jbod map to the firmware. If it is pended command,
+ * issue command and return. If it is first instance of jbod map
+ * issue and receive command.
+ */
+int
+megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend) {
+       int ret = 0;
+       u32 pd_seq_map_sz;
+       struct megasas_cmd *cmd;
+       struct megasas_dcmd_frame *dcmd;
+       struct fusion_context *fusion = instance->ctrl_context;
+       struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
+       dma_addr_t pd_seq_h;
+
+       pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id & 1)];
+       pd_seq_h = fusion->pd_seq_phys[(instance->pd_seq_map_id & 1)];
+       pd_seq_map_sz = sizeof(struct MR_PD_CFG_SEQ_NUM_SYNC) +
+                       (sizeof(struct MR_PD_CFG_SEQ) *
+                       (MAX_PHYSICAL_DEVICES - 1));
+
+       cmd = megasas_get_cmd(instance);
+       if (!cmd) {
+               dev_err(&instance->pdev->dev,
+                       "Could not get mfi cmd. Fail from %s %d\n",
+                       __func__, __LINE__);
+               return -ENOMEM;
+       }
+
+       dcmd = &cmd->frame->dcmd;
+
+       memset(pd_sync, 0, pd_seq_map_sz);
+       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+       dcmd->cmd = MFI_CMD_DCMD;
+       dcmd->cmd_status = 0xFF;
+       dcmd->sge_count = 1;
+       dcmd->timeout = 0;
+       dcmd->pad_0 = 0;
+       dcmd->data_xfer_len = cpu_to_le32(pd_seq_map_sz);
+       dcmd->opcode = cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO);
+       dcmd->sgl.sge32[0].phys_addr = cpu_to_le32(pd_seq_h);
+       dcmd->sgl.sge32[0].length = cpu_to_le32(pd_seq_map_sz);
+
+       if (pend) {
+               dcmd->mbox.b[0] = MEGASAS_DCMD_MBOX_PEND_FLAG;
+               dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_WRITE);
+               instance->jbod_seq_cmd = cmd;
+               instance->instancet->issue_dcmd(instance, cmd);
+               return 0;
+       }
+
+       dcmd->flags = cpu_to_le16(MFI_FRAME_DIR_READ);
+
+       /* Below code is only for non pended DCMD */
+       if (instance->ctrl_context && !instance->mask_interrupts)
+               ret = megasas_issue_blocked_cmd(instance, cmd, 60);
+       else
+               ret = megasas_issue_polled(instance, cmd);
+
+       if (le32_to_cpu(pd_sync->count) > MAX_PHYSICAL_DEVICES) {
+               dev_warn(&instance->pdev->dev,
+                       "driver supports max %d JBOD, but FW reports %d\n",
+                       MAX_PHYSICAL_DEVICES, le32_to_cpu(pd_sync->count));
+               ret = -EINVAL;
+       }
+
+       if (!ret)
+               instance->pd_seq_map_id++;
+
+       megasas_return_cmd(instance, cmd);
+       return ret;
+}
+
 /*
  * megasas_get_ld_map_info -   Returns FW's ld_map structure
  * @instance:                          Adapter soft state
@@ -961,6 +1037,18 @@ megasas_display_intel_branding(struct megasas_instance *instance)
                        break;
                }
                break;
+       case PCI_DEVICE_ID_LSI_CUTLASS_52:
+       case PCI_DEVICE_ID_LSI_CUTLASS_53:
+               switch (instance->pdev->subsystem_device) {
+               case MEGARAID_INTEL_RMS3BC160_SSDID:
+                       dev_info(&instance->pdev->dev, "scsi host %d: %s\n",
+                               instance->host->host_no,
+                               MEGARAID_INTEL_RMS3BC160_BRANDING);
+                       break;
+               default:
+                       break;
+               }
+               break;
        default:
                break;
        }
@@ -977,7 +1065,7 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
 {
        struct megasas_register_set __iomem *reg_set;
        struct fusion_context *fusion;
-       u32 max_cmd;
+       u32 max_cmd, scratch_pad_2;
        int i = 0, count;
 
        fusion = instance->ctrl_context;
@@ -1016,15 +1104,40 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
                (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE *
                 (max_cmd + 1)); /* Extra 1 for SMID 0 */
 
+       scratch_pad_2 = readl(&instance->reg_set->outbound_scratch_pad_2);
+       /* If scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK is set,
+        * Firmware support extended IO chain frame which is 4 times more than
+        * legacy Firmware.
+        * Legacy Firmware - Frame size is (8 * 128) = 1K
+        * 1M IO Firmware  - Frame size is (8 * 128 * 4)  = 4K
+        */
+       if (scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK)
+               instance->max_chain_frame_sz =
+                       ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
+                       MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_1MB_IO;
+       else
+               instance->max_chain_frame_sz =
+                       ((scratch_pad_2 & MEGASAS_MAX_CHAIN_SIZE_MASK) >>
+                       MEGASAS_MAX_CHAIN_SHIFT) * MEGASAS_256K_IO;
+
+       if (instance->max_chain_frame_sz < MEGASAS_CHAIN_FRAME_SZ_MIN) {
+               dev_warn(&instance->pdev->dev, "frame size %d invalid, fall back to legacy max frame size %d\n",
+                       instance->max_chain_frame_sz,
+                       MEGASAS_CHAIN_FRAME_SZ_MIN);
+               instance->max_chain_frame_sz = MEGASAS_CHAIN_FRAME_SZ_MIN;
+       }
+
        fusion->max_sge_in_main_msg =
-         (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE -
-          offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
+               (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE
+                       - offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16;
 
        fusion->max_sge_in_chain =
-               MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION);
+               instance->max_chain_frame_sz
+                       / sizeof(union MPI2_SGE_IO_UNION);
 
-       instance->max_num_sge = rounddown_pow_of_two(
-               fusion->max_sge_in_main_msg + fusion->max_sge_in_chain - 2);
+       instance->max_num_sge =
+               rounddown_pow_of_two(fusion->max_sge_in_main_msg
+                       + fusion->max_sge_in_chain - 2);
 
        /* Used for pass thru MFI frame (DCMD) */
        fusion->chain_offset_mfi_pthru =
@@ -1186,8 +1299,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
 
        fusion = instance->ctrl_context;
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+       if (fusion->adapter_type == INVADER_SERIES) {
                struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end = sgl_ptr;
                sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
                sgl_ptr_end->Flags = 0;
@@ -1204,11 +1316,9 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
                sgl_ptr->Length = cpu_to_le32(sg_dma_len(os_sgl));
                sgl_ptr->Address = cpu_to_le64(sg_dma_address(os_sgl));
                sgl_ptr->Flags = 0;
-               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-                       (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+               if (fusion->adapter_type == INVADER_SERIES)
                        if (i == sge_count - 1)
                                sgl_ptr->Flags = IEEE_SGE_FLAGS_END_OF_LIST;
-               }
                sgl_ptr++;
 
                sg_processed = i + 1;
@@ -1217,10 +1327,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
                    (sge_count > fusion->max_sge_in_main_msg)) {
 
                        struct MPI25_IEEE_SGE_CHAIN64 *sg_chain;
-                       if ((instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_INVADER) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_FURY)) {
+                       if (fusion->adapter_type == INVADER_SERIES) {
                                if ((le16_to_cpu(cmd->io_request->IoFlags) &
                                        MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) !=
                                        MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH)
@@ -1236,10 +1343,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
                        sg_chain = sgl_ptr;
                        /* Prepare chain element */
                        sg_chain->NextChainOffset = 0;
-                       if ((instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_INVADER) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_FURY))
+                       if (fusion->adapter_type == INVADER_SERIES)
                                sg_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT;
                        else
                                sg_chain->Flags =
@@ -1250,7 +1354,7 @@ megasas_make_sgl_fusion(struct megasas_instance *instance,
 
                        sgl_ptr =
                          (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame;
-                       memset(sgl_ptr, 0, MEGASAS_MAX_SZ_CHAIN_FRAME);
+                       memset(sgl_ptr, 0, instance->max_chain_frame_sz);
                }
        }
 
@@ -1556,8 +1660,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                cmd->request_desc->SCSIIO.RequestFlags =
                        (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY
                         << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
-               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-                       (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+               if (fusion->adapter_type == INVADER_SERIES) {
                        if (io_request->RaidContext.regLockFlags ==
                            REGION_TYPE_UNUSED)
                                cmd->request_desc->SCSIIO.RequestFlags =
@@ -1582,7 +1685,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                        scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
 
                if ((raidLUN[0] == 1) &&
-                       (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 2)) {
+                       (local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].validHandles > 1)) {
                        instance->dev_handle = !(instance->dev_handle);
                        io_info.devHandle =
                                local_map_ptr->raidMap.devHndlInfo[io_info.pd_after_lb].devHandle[instance->dev_handle];
@@ -1598,8 +1701,7 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
                cmd->request_desc->SCSIIO.RequestFlags =
                        (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO
                         << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
-               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-                       (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+               if (fusion->adapter_type == INVADER_SERIES) {
                        if (io_request->RaidContext.regLockFlags ==
                            REGION_TYPE_UNUSED)
                                cmd->request_desc->SCSIIO.RequestFlags =
@@ -1722,7 +1824,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
        u16 timeout_limit;
        struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
        struct RAID_CONTEXT     *pRAID_Context;
+       struct MR_PD_CFG_SEQ_NUM_SYNC *pd_sync;
        struct fusion_context *fusion = instance->ctrl_context;
+       pd_sync = (void *)fusion->pd_seq_sync[(instance->pd_seq_map_id - 1) & 1];
 
        device_id = MEGASAS_DEV_INDEX(scmd);
        pd_index = MEGASAS_PD_INDEX(scmd);
@@ -1731,16 +1835,38 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
        io_request = cmd->io_request;
        /* get RAID_Context pointer */
        pRAID_Context = &io_request->RaidContext;
+       pRAID_Context->regLockFlags = 0;
+       pRAID_Context->regLockRowLBA = 0;
+       pRAID_Context->regLockLength = 0;
        io_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
        io_request->LUN[1] = scmd->device->lun;
        pRAID_Context->RAIDFlags = MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD
                << MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT;
 
-       pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
-       pRAID_Context->configSeqNum = 0;
-       local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
-       io_request->DevHandle =
-               local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+       /* If FW supports PD sequence number */
+       if (instance->use_seqnum_jbod_fp &&
+               instance->pd_list[pd_index].driveType == TYPE_DISK) {
+               /* TgtId must be incremented by 255 as jbod seq number is index
+                * below raid map
+                */
+               pRAID_Context->VirtualDiskTgtId =
+                       cpu_to_le16(device_id + (MAX_PHYSICAL_DEVICES - 1));
+               pRAID_Context->configSeqNum = pd_sync->seq[pd_index].seqNum;
+               io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
+               pRAID_Context->regLockFlags |=
+                       (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
+       } else if (fusion->fast_path_io) {
+               pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
+               pRAID_Context->configSeqNum = 0;
+               local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
+               io_request->DevHandle =
+                       local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
+       } else {
+               /* Want to send all IO via FW path */
+               pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
+               pRAID_Context->configSeqNum = 0;
+               io_request->DevHandle = cpu_to_le16(0xFFFF);
+       }
 
        cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
        cmd->request_desc->SCSIIO.MSIxIndex =
@@ -1755,22 +1881,16 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
                        (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO <<
                                MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
                pRAID_Context->timeoutValue = cpu_to_le16(os_timeout_value);
+               pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
        } else {
                /* system pd Fast Path */
                io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
-               pRAID_Context->regLockFlags = 0;
-               pRAID_Context->regLockRowLBA = 0;
-               pRAID_Context->regLockLength = 0;
                timeout_limit = (scmd->device->type == TYPE_DISK) ?
                                255 : 0xFFFF;
                pRAID_Context->timeoutValue =
                        cpu_to_le16((os_timeout_value > timeout_limit) ?
                        timeout_limit : os_timeout_value);
-               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-                       (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
-                       cmd->request_desc->SCSIIO.RequestFlags |=
-                               (MEGASAS_REQ_DESCRIPT_FLAGS_NO_LOCK <<
-                               MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+               if (fusion->adapter_type == INVADER_SERIES) {
                        pRAID_Context->Type = MPI2_TYPE_CUDA;
                        pRAID_Context->nseg = 0x1;
                        io_request->IoFlags |=
@@ -1796,7 +1916,7 @@ megasas_build_io_fusion(struct megasas_instance *instance,
                        struct scsi_cmnd *scp,
                        struct megasas_cmd_fusion *cmd)
 {
-       u32 sge_count;
+       u16 sge_count;
        u8  cmd_type;
        struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request;
 
@@ -1854,7 +1974,11 @@ megasas_build_io_fusion(struct megasas_instance *instance,
                return 1;
        }
 
+       /* numSGE store lower 8 bit of sge_count.
+        * numSGEExt store higher 8 bit of sge_count
+        */
        io_request->RaidContext.numSGE = sge_count;
+       io_request->RaidContext.numSGEExt = (u8)(sge_count >> 8);
 
        io_request->SGLFlags = cpu_to_le16(MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
 
@@ -2084,10 +2208,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
                 * pending to be completed
                 */
                if (threshold_reply_count >= THRESHOLD_REPLY_COUNT) {
-                       if ((instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_INVADER) ||
-                               (instance->pdev->device ==
-                               PCI_DEVICE_ID_LSI_FURY))
+                       if (fusion->adapter_type == INVADER_SERIES)
                                writel(((MSIxIndex & 0x7) << 24) |
                                        fusion->last_reply_idx[MSIxIndex],
                                        instance->reply_post_host_index_addr[MSIxIndex/8]);
@@ -2103,8 +2224,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)
                return IRQ_NONE;
 
        wmb();
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
+       if (fusion->adapter_type == INVADER_SERIES)
                writel(((MSIxIndex & 0x7) << 24) |
                        fusion->last_reply_idx[MSIxIndex],
                        instance->reply_post_host_index_addr[MSIxIndex/8]);
@@ -2227,8 +2347,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
 
        io_req = cmd->io_request;
 
-       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER) ||
-               (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY)) {
+       if (fusion->adapter_type == INVADER_SERIES) {
                struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr_end =
                        (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL;
                sgl_ptr_end += fusion->max_sge_in_main_msg - 1;
@@ -2248,7 +2367,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
        mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
                MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
 
-       mpi25_ieee_chain->Length = cpu_to_le32(MEGASAS_MAX_SZ_CHAIN_FRAME);
+       mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz);
 
        return 0;
 }
@@ -2384,6 +2503,70 @@ static int
 megasas_adp_reset_fusion(struct megasas_instance *instance,
                         struct megasas_register_set __iomem *regs)
 {
+       u32 host_diag, abs_state, retry;
+
+       /* Now try to reset the chip */
+       writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_1ST_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_2ND_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_3RD_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_4TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_5TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+       writel(MPI2_WRSEQ_6TH_KEY_VALUE, &instance->reg_set->fusion_seq_offset);
+
+       /* Check that the diag write enable (DRWE) bit is on */
+       host_diag = readl(&instance->reg_set->fusion_host_diag);
+       retry = 0;
+       while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
+               msleep(100);
+               host_diag = readl(&instance->reg_set->fusion_host_diag);
+               if (retry++ == 100) {
+                       dev_warn(&instance->pdev->dev,
+                               "Host diag unlock failed from %s %d\n",
+                               __func__, __LINE__);
+                       break;
+               }
+       }
+       if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
+               return -1;
+
+       /* Send chip reset command */
+       writel(host_diag | HOST_DIAG_RESET_ADAPTER,
+               &instance->reg_set->fusion_host_diag);
+       msleep(3000);
+
+       /* Make sure reset adapter bit is cleared */
+       host_diag = readl(&instance->reg_set->fusion_host_diag);
+       retry = 0;
+       while (host_diag & HOST_DIAG_RESET_ADAPTER) {
+               msleep(100);
+               host_diag = readl(&instance->reg_set->fusion_host_diag);
+               if (retry++ == 1000) {
+                       dev_warn(&instance->pdev->dev,
+                               "Diag reset adapter never cleared %s %d\n",
+                               __func__, __LINE__);
+                       break;
+               }
+       }
+       if (host_diag & HOST_DIAG_RESET_ADAPTER)
+               return -1;
+
+       abs_state = instance->instancet->read_fw_status_reg(instance->reg_set)
+                       & MFI_STATE_MASK;
+       retry = 0;
+
+       while ((abs_state <= MFI_STATE_FW_INIT) && (retry++ < 1000)) {
+               msleep(100);
+               abs_state = instance->instancet->
+                       read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
+       }
+       if (abs_state <= MFI_STATE_FW_INIT) {
+               dev_warn(&instance->pdev->dev,
+                       "fw state < MFI_STATE_FW_INIT, state = 0x%x %s %d\n",
+                       abs_state, __func__, __LINE__);
+               return -1;
+       }
+
        return 0;
 }
 
@@ -2512,8 +2695,10 @@ void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
                        continue;
                req_desc = megasas_get_request_descriptor
                                        (instance, smid - 1);
-               if (req_desc && (cmd_mfi->frame->dcmd.opcode !=
-                               cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)))
+               if (req_desc && ((cmd_mfi->frame->dcmd.opcode !=
+                               cpu_to_le32(MR_DCMD_LD_MAP_GET_INFO)) &&
+                                (cmd_mfi->frame->dcmd.opcode !=
+                               cpu_to_le32(MR_DCMD_SYSTEM_PD_MAP_GET_INFO))))
                        megasas_fire_cmd_fusion(instance, req_desc);
                else
                        megasas_return_cmd(instance, cmd_mfi);
@@ -2547,11 +2732,11 @@ int megasas_check_mpio_paths(struct megasas_instance *instance,
 /* Core fusion reset function */
 int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
 {
-       int retval = SUCCESS, i, retry = 0, convert = 0;
+       int retval = SUCCESS, i, convert = 0;
        struct megasas_instance *instance;
        struct megasas_cmd_fusion *cmd_fusion;
        struct fusion_context *fusion;
-       u32 host_diag, abs_state, status_reg, reset_adapter;
+       u32 abs_state, status_reg, reset_adapter;
        u32 io_timeout_in_crash_mode = 0;
        struct scsi_cmnd *scmd_local = NULL;
 
@@ -2705,82 +2890,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
 
                /* Now try to reset the chip */
                for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) {
-                       writel(MPI2_WRSEQ_FLUSH_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_1ST_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_2ND_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_3RD_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_4TH_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_5TH_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-                       writel(MPI2_WRSEQ_6TH_KEY_VALUE,
-                              &instance->reg_set->fusion_seq_offset);
-
-                       /* Check that the diag write enable (DRWE) bit is on */
-                       host_diag = readl(&instance->reg_set->fusion_host_diag);
-                       retry = 0;
-                       while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) {
-                               msleep(100);
-                               host_diag =
-                               readl(&instance->reg_set->fusion_host_diag);
-                               if (retry++ == 100) {
-                                       dev_warn(&instance->pdev->dev,
-                                              "Host diag unlock failed! "
-                                              "for scsi%d\n",
-                                               instance->host->host_no);
-                                       break;
-                               }
-                       }
-                       if (!(host_diag & HOST_DIAG_WRITE_ENABLE))
-                               continue;
 
-                       /* Send chip reset command */
-                       writel(host_diag | HOST_DIAG_RESET_ADAPTER,
-                              &instance->reg_set->fusion_host_diag);
-                       msleep(3000);
-
-                       /* Make sure reset adapter bit is cleared */
-                       host_diag = readl(&instance->reg_set->fusion_host_diag);
-                       retry = 0;
-                       while (host_diag & HOST_DIAG_RESET_ADAPTER) {
-                               msleep(100);
-                               host_diag =
-                               readl(&instance->reg_set->fusion_host_diag);
-                               if (retry++ == 1000) {
-                                       dev_warn(&instance->pdev->dev,
-                                              "Diag reset adapter never "
-                                              "cleared for scsi%d!\n",
-                                               instance->host->host_no);
-                                       break;
-                               }
-                       }
-                       if (host_diag & HOST_DIAG_RESET_ADAPTER)
+                       if (instance->instancet->adp_reset
+                               (instance, instance->reg_set))
                                continue;
 
-                       abs_state =
-                               instance->instancet->read_fw_status_reg(
-                                       instance->reg_set) & MFI_STATE_MASK;
-                       retry = 0;
-
-                       while ((abs_state <= MFI_STATE_FW_INIT) &&
-                              (retry++ < 1000)) {
-                               msleep(100);
-                               abs_state =
-                               instance->instancet->read_fw_status_reg(
-                                       instance->reg_set) & MFI_STATE_MASK;
-                       }
-                       if (abs_state <= MFI_STATE_FW_INIT) {
-                               dev_warn(&instance->pdev->dev, "firmware "
-                                      "state < MFI_STATE_FW_INIT, state = "
-                                      "0x%x for scsi%d\n", abs_state,
-                                       instance->host->host_no);
-                               continue;
-                       }
-
                        /* Wait for FW to become ready */
                        if (megasas_transition_to_ready(instance, 1)) {
                                dev_warn(&instance->pdev->dev, "Failed to "
@@ -2816,6 +2930,8 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
                        if (!megasas_get_map_info(instance))
                                megasas_sync_map_info(instance);
 
+                       megasas_setup_jbod_map(instance);
+
                        clear_bit(MEGASAS_FUSION_IN_RESET,
                                  &instance->reset_flags);
                        instance->instancet->enable_intr(instance);
index ced6dc0cf8e8ab7bf6e00ec1710ee24a5e802a4e..473005c99b4406d241cfb92ffbfea0ded5a124df 100644 (file)
 #define _MEGARAID_SAS_FUSION_H_
 
 /* Fusion defines */
-#define MEGASAS_MAX_SZ_CHAIN_FRAME 1024
+#define MEGASAS_CHAIN_FRAME_SZ_MIN 1024
 #define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009)
+#define MEGASAS_MAX_CHAIN_SHIFT                        5
+#define MEGASAS_MAX_CHAIN_SIZE_UNITS_MASK      0x400000
+#define MEGASAS_MAX_CHAIN_SIZE_MASK            0x3E0
+#define MEGASAS_256K_IO                                128
+#define MEGASAS_1MB_IO                         (MEGASAS_256K_IO * 4)
 #define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256
 #define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST   0xF0
 #define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST         0xF1
@@ -89,6 +94,12 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
 #define MEGASAS_FP_CMD_LEN     16
 #define MEGASAS_FUSION_IN_RESET 0
 #define THRESHOLD_REPLY_COUNT 50
+#define JBOD_MAPS_COUNT        2
+
+enum MR_FUSION_ADAPTER_TYPE {
+       THUNDERBOLT_SERIES = 0,
+       INVADER_SERIES = 1,
+};
 
 /*
  * Raid Context structure which describes MegaRAID specific IO Parameters
@@ -117,7 +128,9 @@ struct RAID_CONTEXT {
        u8      numSGE;
        __le16  configSeqNum;
        u8      spanArm;
-       u8      resvd2[3];
+       u8      priority;
+       u8      numSGEExt;
+       u8      resvd2;
 };
 
 #define RAID_CTX_SPANARM_ARM_SHIFT     (0)
@@ -486,6 +499,7 @@ struct MPI2_IOC_INIT_REQUEST {
 #define MAX_PHYSICAL_DEVICES 256
 #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
 #define MR_DCMD_LD_MAP_GET_INFO             0x0300e101
+#define MR_DCMD_SYSTEM_PD_MAP_GET_INFO      0x0200e102
 #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC  0x010e8485   /* SR-IOV HB alloc*/
 #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111   0x03200200
 #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS       0x03150200
@@ -789,6 +803,21 @@ struct MR_FW_RAID_MAP_EXT {
        struct MR_LD_SPAN_MAP      ldSpanMap[MAX_LOGICAL_DRIVES_EXT];
 };
 
+/*
+ *  * define MR_PD_CFG_SEQ structure for system PDs
+ *   */
+struct MR_PD_CFG_SEQ {
+       __le16 seqNum;
+       __le16 devHandle;
+       u8  reserved[4];
+} __packed;
+
+struct MR_PD_CFG_SEQ_NUM_SYNC {
+       __le32 size;
+       __le32 count;
+       struct MR_PD_CFG_SEQ seq[1];
+} __packed;
+
 struct fusion_context {
        struct megasas_cmd_fusion **cmd_list;
        dma_addr_t req_frames_desc_phys;
@@ -828,9 +857,12 @@ struct fusion_context {
        u32 current_map_sz;
        u32 drv_map_sz;
        u32 drv_map_pages;
+       struct MR_PD_CFG_SEQ_NUM_SYNC   *pd_seq_sync[JBOD_MAPS_COUNT];
+       dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
        u8 fast_path_io;
        struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT];
        LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
+       u8 adapter_type;
 };
 
 union desc_value {
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig
deleted file mode 100644 (file)
index 657b45c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Kernel configuration file for the MPT2SAS
-#
-# This code is based on drivers/scsi/mpt2sas/Kconfig
-# Copyright (C) 2007-2014  LSI Corporation
-#  (mailto:DL-MPTFusionLinux@lsi.com)
-
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# NO WARRANTY
-# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
-# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
-# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
-# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
-# solely responsible for determining the appropriateness of using and
-# distributing the Program and assumes all risks associated with its
-# exercise of rights under this Agreement, including but not limited to
-# the risks and costs of program errors, damage to or loss of data,
-# programs or equipment, and unavailability or interruption of operations.
-
-# DISCLAIMER OF LIABILITY
-# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
-# 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.
-
-config SCSI_MPT2SAS
-       tristate "LSI MPT Fusion SAS 2.0 Device Driver"
-       depends on PCI && SCSI
-       select SCSI_SAS_ATTRS
-       select RAID_ATTRS
-       ---help---
-       This driver supports PCI-Express SAS 6Gb/s Host Adapters.
-
-config SCSI_MPT2SAS_MAX_SGE
-       int "LSI MPT Fusion Max number of SG Entries (16 - 128)"
-       depends on PCI && SCSI && SCSI_MPT2SAS
-       default "128"
-       range 16 128
-       ---help---
-       This option allows you to specify the maximum number of scatter-
-       gather entries per I/O. The driver default is 128, which matches
-       SAFE_PHYS_SEGMENTS.  However, it may decreased down to 16.
-       Decreasing this parameter will reduce memory requirements
-       on a per controller instance.
-
-config SCSI_MPT2SAS_LOGGING
-       bool "LSI MPT Fusion logging facility"
-       depends on PCI && SCSI && SCSI_MPT2SAS
-       ---help---
-       This turns on a logging facility.
diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile
deleted file mode 100644 (file)
index 728f047..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# mpt2sas makefile
-obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o
-mpt2sas-y +=  mpt2sas_base.o        \
-               mpt2sas_config.o    \
-               mpt2sas_scsih.o     \
-               mpt2sas_transport.o \
-               mpt2sas_ctl.o
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
deleted file mode 100644 (file)
index 7fc6f23..0000000
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2.h
- *          Title:  MPI Message independent structures and definitions
- *                  including System Interface Register Set and
- *                  scatter/gather formats.
- *  Creation Date:  June 21, 2006
- *
- *  mpi2.h Version:  02.00.35
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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.
- *  07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
- *  10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added MSI-x index mask and shift for Reply Post Host
- *                      Index register.
- *                      Added function code for Host Based Discovery Action.
- *  02-10-10  02.00.15  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL.
- *                      Added defines for product-specific range of message
- *                      function codes, 0xF0 to 0xFF.
- *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added alternative defines for the SGE Direction bit.
- *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
- *  11-10-10  02.00.18  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define.
- *  02-23-11  02.00.19  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added MPI2_FUNCTION_SEND_HOST_MESSAGE.
- *  03-09-11  02.00.20  Bumped MPI2_HEADER_VERSION_UNIT.
- *  05-25-11  02.00.21  Bumped MPI2_HEADER_VERSION_UNIT.
- *  08-24-11  02.00.22  Bumped MPI2_HEADER_VERSION_UNIT.
- *  11-18-11  02.00.23  Bumped MPI2_HEADER_VERSION_UNIT.
- *  02-06-12  02.00.24  Bumped MPI2_HEADER_VERSION_UNIT.
- *  03-29-12  02.00.25  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added Hard Reset delay timings.
- *  07-10-12  02.00.26  Bumped MPI2_HEADER_VERSION_UNIT.
- *  07-26-12  02.00.27  Bumped MPI2_HEADER_VERSION_UNIT.
- *  11-27-12  02.00.28  Bumped MPI2_HEADER_VERSION_UNIT.
- *  12-20-12  02.00.29  Bumped MPI2_HEADER_VERSION_UNIT.
- *                     Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET.
- *  04-09-13  02.00.30  Bumped MPI2_HEADER_VERSION_UNIT.
- *  04-17-13  02.00.31  Bumped MPI2_HEADER_VERSION_UNIT.
- *  08-19-13  02.00.32  Bumped MPI2_HEADER_VERSION_UNIT.
- *  12-05-13  02.00.33  Bumped MPI2_HEADER_VERSION_UNIT.
- *  01-08-14  02.00.34  Bumped MPI2_HEADER_VERSION_UNIT.
- *  06-13-14  02.00.35  Bumped MPI2_HEADER_VERSION_UNIT.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_H
-#define MPI2_H
-
-
-/*****************************************************************************
-*
-*        MPI Version Definitions
-*
-*****************************************************************************/
-
-#define MPI2_VERSION_MAJOR                  (0x02)
-#define MPI2_VERSION_MINOR                  (0x00)
-#define MPI2_VERSION_MAJOR_MASK             (0xFF00)
-#define MPI2_VERSION_MAJOR_SHIFT            (8)
-#define MPI2_VERSION_MINOR_MASK             (0x00FF)
-#define MPI2_VERSION_MINOR_SHIFT            (0)
-#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) |   \
-                                      MPI2_VERSION_MINOR)
-
-#define MPI2_VERSION_02_00                  (0x0200)
-
-/* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x23)
-#define MPI2_HEADER_VERSION_DEV             (0x00)
-#define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
-#define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
-#define MPI2_HEADER_VERSION_DEV_MASK        (0x00FF)
-#define MPI2_HEADER_VERSION_DEV_SHIFT       (0)
-#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
-
-
-/*****************************************************************************
-*
-*        IOC State Definitions
-*
-*****************************************************************************/
-
-#define MPI2_IOC_STATE_RESET               (0x00000000)
-#define MPI2_IOC_STATE_READY               (0x10000000)
-#define MPI2_IOC_STATE_OPERATIONAL         (0x20000000)
-#define MPI2_IOC_STATE_FAULT               (0x40000000)
-
-#define MPI2_IOC_STATE_MASK                (0xF0000000)
-#define MPI2_IOC_STATE_SHIFT               (28)
-
-/* Fault state range for prodcut specific codes */
-#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN                 (0x0000)
-#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX                 (0xEFFF)
-
-
-/*****************************************************************************
-*
-*        System Interface Register Definitions
-*
-*****************************************************************************/
-
-typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
-{
-    U32         Doorbell;                   /* 0x00 */
-    U32         WriteSequence;              /* 0x04 */
-    U32         HostDiagnostic;             /* 0x08 */
-    U32         Reserved1;                  /* 0x0C */
-    U32         DiagRWData;                 /* 0x10 */
-    U32         DiagRWAddressLow;           /* 0x14 */
-    U32         DiagRWAddressHigh;          /* 0x18 */
-    U32         Reserved2[5];               /* 0x1C */
-    U32         HostInterruptStatus;        /* 0x30 */
-    U32         HostInterruptMask;          /* 0x34 */
-    U32         DCRData;                    /* 0x38 */
-    U32         DCRAddress;                 /* 0x3C */
-    U32         Reserved3[2];               /* 0x40 */
-    U32         ReplyFreeHostIndex;         /* 0x48 */
-    U32         Reserved4[8];               /* 0x4C */
-    U32         ReplyPostHostIndex;         /* 0x6C */
-    U32         Reserved5;                  /* 0x70 */
-    U32         HCBSize;                    /* 0x74 */
-    U32         HCBAddressLow;              /* 0x78 */
-    U32         HCBAddressHigh;             /* 0x7C */
-    U32         Reserved6[16];              /* 0x80 */
-    U32         RequestDescriptorPostLow;   /* 0xC0 */
-    U32         RequestDescriptorPostHigh;  /* 0xC4 */
-    U32         Reserved7[14];              /* 0xC8 */
-} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
-  Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
-
-/*
- * Defines for working with the Doorbell register.
- */
-#define MPI2_DOORBELL_OFFSET                    (0x00000000)
-
-/* IOC --> System values */
-#define MPI2_DOORBELL_USED                      (0x08000000)
-#define MPI2_DOORBELL_WHO_INIT_MASK             (0x07000000)
-#define MPI2_DOORBELL_WHO_INIT_SHIFT            (24)
-#define MPI2_DOORBELL_FAULT_CODE_MASK           (0x0000FFFF)
-#define MPI2_DOORBELL_DATA_MASK                 (0x0000FFFF)
-
-/* System --> IOC values */
-#define MPI2_DOORBELL_FUNCTION_MASK             (0xFF000000)
-#define MPI2_DOORBELL_FUNCTION_SHIFT            (24)
-#define MPI2_DOORBELL_ADD_DWORDS_MASK           (0x00FF0000)
-#define MPI2_DOORBELL_ADD_DWORDS_SHIFT          (16)
-
-
-/*
- * Defines for the WriteSequence register
- */
-#define MPI2_WRITE_SEQUENCE_OFFSET              (0x00000004)
-#define MPI2_WRSEQ_KEY_VALUE_MASK               (0x0000000F)
-#define MPI2_WRSEQ_FLUSH_KEY_VALUE              (0x0)
-#define MPI2_WRSEQ_1ST_KEY_VALUE                (0xF)
-#define MPI2_WRSEQ_2ND_KEY_VALUE                (0x4)
-#define MPI2_WRSEQ_3RD_KEY_VALUE                (0xB)
-#define MPI2_WRSEQ_4TH_KEY_VALUE                (0x2)
-#define MPI2_WRSEQ_5TH_KEY_VALUE                (0x7)
-#define MPI2_WRSEQ_6TH_KEY_VALUE                (0xD)
-
-/*
- * Defines for the HostDiagnostic register
- */
-#define MPI2_HOST_DIAGNOSTIC_OFFSET             (0x00000008)
-
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK       (0x00001800)
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT    (0x00000000)
-#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW       (0x00000800)
-
-#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG           (0x00000400)
-#define MPI2_DIAG_FORCE_HCB_ON_RESET            (0x00000200)
-#define MPI2_DIAG_HCB_MODE                      (0x00000100)
-#define MPI2_DIAG_DIAG_WRITE_ENABLE             (0x00000080)
-#define MPI2_DIAG_FLASH_BAD_SIG                 (0x00000040)
-#define MPI2_DIAG_RESET_HISTORY                 (0x00000020)
-#define MPI2_DIAG_DIAG_RW_ENABLE                (0x00000010)
-#define MPI2_DIAG_RESET_ADAPTER                 (0x00000004)
-#define MPI2_DIAG_HOLD_IOC_RESET                (0x00000002)
-
-/*
- * Offsets for DiagRWData and address
- */
-#define MPI2_DIAG_RW_DATA_OFFSET                (0x00000010)
-#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET         (0x00000014)
-#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET        (0x00000018)
-
-/*
- * Defines for the HostInterruptStatus register
- */
-#define MPI2_HOST_INTERRUPT_STATUS_OFFSET       (0x00000030)
-#define MPI2_HIS_SYS2IOC_DB_STATUS              (0x80000000)
-#define MPI2_HIS_IOP_DOORBELL_STATUS            MPI2_HIS_SYS2IOC_DB_STATUS
-#define MPI2_HIS_RESET_IRQ_STATUS               (0x40000000)
-#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT     (0x00000008)
-#define MPI2_HIS_IOC2SYS_DB_STATUS              (0x00000001)
-#define MPI2_HIS_DOORBELL_INTERRUPT             MPI2_HIS_IOC2SYS_DB_STATUS
-
-/*
- * Defines for the HostInterruptMask register
- */
-#define MPI2_HOST_INTERRUPT_MASK_OFFSET         (0x00000034)
-#define MPI2_HIM_RESET_IRQ_MASK                 (0x40000000)
-#define MPI2_HIM_REPLY_INT_MASK                 (0x00000008)
-#define MPI2_HIM_RIM                            MPI2_HIM_REPLY_INT_MASK
-#define MPI2_HIM_IOC2SYS_DB_MASK                (0x00000001)
-#define MPI2_HIM_DIM                            MPI2_HIM_IOC2SYS_DB_MASK
-
-/*
- * Offsets for DCRData and address
- */
-#define MPI2_DCR_DATA_OFFSET                    (0x00000038)
-#define MPI2_DCR_ADDRESS_OFFSET                 (0x0000003C)
-
-/*
- * Offset for the Reply Free Queue
- */
-#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET       (0x00000048)
-
-/*
- * Defines for the Reply Descriptor Post Queue
- */
-#define MPI2_REPLY_POST_HOST_INDEX_OFFSET       (0x0000006C)
-#define MPI2_REPLY_POST_HOST_INDEX_MASK         (0x00FFFFFF)
-#define MPI2_RPHI_MSIX_INDEX_MASK               (0xFF000000)
-#define MPI2_RPHI_MSIX_INDEX_SHIFT              (24)
-#define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET  (0x0000030C) /* MPI v2.5 only */
-
-/*
- * Defines for the HCBSize and address
- */
-#define MPI2_HCB_SIZE_OFFSET                    (0x00000074)
-#define MPI2_HCB_SIZE_SIZE_MASK                 (0xFFFFF000)
-#define MPI2_HCB_SIZE_HCB_ENABLE                (0x00000001)
-
-#define MPI2_HCB_ADDRESS_LOW_OFFSET             (0x00000078)
-#define MPI2_HCB_ADDRESS_HIGH_OFFSET            (0x0000007C)
-
-/*
- * Offsets for the Request Queue
- */
-#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET     (0x000000C0)
-#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET    (0x000000C4)
-
-
-/* Hard Reset delay timings */
-#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC     (50000)
-#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC    (255000)
-#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC    (256000)
-
-/*****************************************************************************
-*
-*        Message Descriptors
-*
-*****************************************************************************/
-
-/* Request Descriptors */
-
-/* Default Request Descriptor */
-typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
-{
-    U8              RequestFlags;               /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U16             LMID;                       /* 0x04 */
-    U16             DescriptorTypeDependent;    /* 0x06 */
-} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
-  Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
-
-/* defines for the RequestFlags field */
-#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK               (0x0E)
-#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO                 (0x00)
-#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)
-
-
-/* High Priority Request Descriptor */
-typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
-{
-    U8              RequestFlags;               /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U16             LMID;                       /* 0x04 */
-    U16             Reserved1;                  /* 0x06 */
-} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
-  Mpi2HighPriorityRequestDescriptor_t,
-  MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
-
-
-/* SCSI IO Request Descriptor */
-typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
-{
-    U8              RequestFlags;               /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U16             LMID;                       /* 0x04 */
-    U16             DevHandle;                  /* 0x06 */
-} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
-  Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
-
-
-/* SCSI Target Request Descriptor */
-typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
-{
-    U8              RequestFlags;               /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U16             LMID;                       /* 0x04 */
-    U16             IoIndex;                    /* 0x06 */
-} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
-  MPI2_POINTER PTR_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;
-    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;
-
-
-/* Reply Descriptors */
-
-/* Default Reply Descriptor */
-typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
-{
-    U8              ReplyFlags;                 /* 0x00 */
-    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_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)
-#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK             (0xFFFFFFFF)
-
-/* Address Reply Descriptor */
-typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
-{
-    U8              ReplyFlags;                 /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U32             ReplyFrameAddress;          /* 0x04 */
-} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
-  Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
-
-#define MPI2_ADDRESS_REPLY_SMID_INVALID                 (0x00)
-
-
-/* SCSI IO Success Reply Descriptor */
-typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
-{
-    U8              ReplyFlags;                 /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U16             TaskTag;                    /* 0x04 */
-    U16             Reserved1;                  /* 0x06 */
-} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
-  Mpi2SCSIIOSuccessReplyDescriptor_t,
-  MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
-
-
-/* TargetAssist Success Reply Descriptor */
-typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
-{
-    U8              ReplyFlags;                 /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U16             SMID;                       /* 0x02 */
-    U8              SequenceNumber;             /* 0x04 */
-    U8              Reserved1;                  /* 0x05 */
-    U16             IoIndex;                    /* 0x06 */
-} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
-  Mpi2TargetAssistSuccessReplyDescriptor_t,
-  MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
-
-
-/* Target Command Buffer Reply Descriptor */
-typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
-{
-    U8              ReplyFlags;                 /* 0x00 */
-    U8              MSIxIndex;                  /* 0x01 */
-    U8              VP_ID;                      /* 0x02 */
-    U8              Flags;                      /* 0x03 */
-    U16             InitiatorDevHandle;         /* 0x04 */
-    U16             IoIndex;                    /* 0x06 */
-} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
-  MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
-  Mpi2TargetCommandBufferReplyDescriptor_t,
-  MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
-
-/* defines for Flags field */
-#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;
-    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;
-
-
-
-/*****************************************************************************
-*
-*        Message Functions
-*
-*****************************************************************************/
-
-#define MPI2_FUNCTION_SCSI_IO_REQUEST               (0x00) /* SCSI IO */
-#define MPI2_FUNCTION_SCSI_TASK_MGMT                (0x01) /* SCSI Task Management */
-#define MPI2_FUNCTION_IOC_INIT                      (0x02) /* IOC Init */
-#define MPI2_FUNCTION_IOC_FACTS                     (0x03) /* IOC Facts */
-#define MPI2_FUNCTION_CONFIG                        (0x04) /* Configuration */
-#define MPI2_FUNCTION_PORT_FACTS                    (0x05) /* Port Facts */
-#define MPI2_FUNCTION_PORT_ENABLE                   (0x06) /* Port Enable */
-#define MPI2_FUNCTION_EVENT_NOTIFICATION            (0x07) /* Event Notification */
-#define MPI2_FUNCTION_EVENT_ACK                     (0x08) /* Event Acknowledge */
-#define MPI2_FUNCTION_FW_DOWNLOAD                   (0x09) /* FW Download */
-#define MPI2_FUNCTION_TARGET_ASSIST                 (0x0B) /* Target Assist */
-#define MPI2_FUNCTION_TARGET_STATUS_SEND            (0x0C) /* Target Status Send */
-#define MPI2_FUNCTION_TARGET_MODE_ABORT             (0x0D) /* Target Mode Abort */
-#define MPI2_FUNCTION_FW_UPLOAD                     (0x12) /* FW Upload */
-#define MPI2_FUNCTION_RAID_ACTION                   (0x15) /* RAID Action */
-#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH      (0x16) /* SCSI IO RAID Passthrough */
-#define MPI2_FUNCTION_TOOLBOX                       (0x17) /* Toolbox */
-#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR      (0x18) /* SCSI Enclosure Processor */
-#define MPI2_FUNCTION_SMP_PASSTHROUGH               (0x1A) /* SMP Passthrough */
-#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL           (0x1B) /* SAS IO Unit Control */
-#define MPI2_FUNCTION_SATA_PASSTHROUGH              (0x1C) /* SATA Passthrough */
-#define MPI2_FUNCTION_DIAG_BUFFER_POST              (0x1D) /* Diagnostic Buffer Post */
-#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*/
-/* Host Based Discovery Action */
-#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION   (0x2F)
-/* Power Management Control */
-#define MPI2_FUNCTION_PWR_MGMT_CONTROL              (0x30)
-/* Send Host Message */
-#define MPI2_FUNCTION_SEND_HOST_MESSAGE             (0x31)
-/* beginning of product-specific range */
-#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC          (0xF0)
-/* end of product-specific range */
-#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC          (0xFF)
-
-
-
-
-/* Doorbell functions */
-#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET        (0x40)
-#define MPI2_FUNCTION_HANDSHAKE                     (0x42)
-
-
-/*****************************************************************************
-*
-*        IOC Status Values
-*
-*****************************************************************************/
-
-/* mask for IOCStatus status value */
-#define MPI2_IOCSTATUS_MASK                     (0x7FFF)
-
-/****************************************************************************
-*  Common IOCStatus values for all replies
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SUCCESS                      (0x0000)
-#define MPI2_IOCSTATUS_INVALID_FUNCTION             (0x0001)
-#define MPI2_IOCSTATUS_BUSY                         (0x0002)
-#define MPI2_IOCSTATUS_INVALID_SGL                  (0x0003)
-#define MPI2_IOCSTATUS_INTERNAL_ERROR               (0x0004)
-#define MPI2_IOCSTATUS_INVALID_VPID                 (0x0005)
-#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES       (0x0006)
-#define MPI2_IOCSTATUS_INVALID_FIELD                (0x0007)
-#define MPI2_IOCSTATUS_INVALID_STATE                (0x0008)
-#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED       (0x0009)
-
-/****************************************************************************
-*  Config IOCStatus values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION        (0x0020)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE          (0x0021)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE          (0x0022)
-#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA          (0x0023)
-#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS           (0x0024)
-#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT           (0x0025)
-
-/****************************************************************************
-*  SCSI IO Reply
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR         (0x0040)
-#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE       (0x0042)
-#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE        (0x0043)
-#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN            (0x0044)
-#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN           (0x0045)
-#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR           (0x0046)
-#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR          (0x0047)
-#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED         (0x0048)
-#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH       (0x0049)
-#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED        (0x004A)
-#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED          (0x004B)
-#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED          (0x004C)
-
-/****************************************************************************
-*  For use by SCSI Initiator and SCSI Target end-to-end data protection
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR             (0x004D)
-#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR           (0x004E)
-#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR           (0x004F)
-
-/****************************************************************************
-*  SCSI Target values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX      (0x0062)
-#define MPI2_IOCSTATUS_TARGET_ABORTED               (0x0063)
-#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE     (0x0064)
-#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION         (0x0065)
-#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH   (0x006A)
-#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR     (0x006D)
-#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA   (0x006E)
-#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT          (0x006F)
-#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT       (0x0070)
-#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED          (0x0071)
-
-/****************************************************************************
-*  Serial Attached SCSI values
-****************************************************************************/
-
-#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED       (0x0090)
-#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN         (0x0091)
-
-/****************************************************************************
-*  Diagnostic Buffer Post / Diagnostic Release values
-****************************************************************************/
-
-#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)
-
-/****************************************************************************
-*  IOCLogInfo Types
-****************************************************************************/
-
-#define MPI2_IOCLOGINFO_TYPE_MASK               (0xF0000000)
-#define MPI2_IOCLOGINFO_TYPE_SHIFT              (28)
-#define MPI2_IOCLOGINFO_TYPE_NONE               (0x0)
-#define MPI2_IOCLOGINFO_TYPE_SCSI               (0x1)
-#define MPI2_IOCLOGINFO_TYPE_FC                 (0x2)
-#define MPI2_IOCLOGINFO_TYPE_SAS                (0x3)
-#define MPI2_IOCLOGINFO_TYPE_ISCSI              (0x4)
-#define MPI2_IOCLOGINFO_LOG_DATA_MASK           (0x0FFFFFFF)
-
-
-/*****************************************************************************
-*
-*        Standard Message Structures
-*
-*****************************************************************************/
-
-/****************************************************************************
-* Request Message Header for all request messages
-****************************************************************************/
-
-typedef struct _MPI2_REQUEST_HEADER
-{
-    U16             FunctionDependent1;         /* 0x00 */
-    U8              ChainOffset;                /* 0x02 */
-    U8              Function;                   /* 0x03 */
-    U16             FunctionDependent2;         /* 0x04 */
-    U8              FunctionDependent3;         /* 0x06 */
-    U8              MsgFlags;                   /* 0x07 */
-    U8              VP_ID;                      /* 0x08 */
-    U8              VF_ID;                      /* 0x09 */
-    U16             Reserved1;                  /* 0x0A */
-} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER,
-  MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t;
-
-
-/****************************************************************************
-*  Default Reply
-****************************************************************************/
-
-typedef struct _MPI2_DEFAULT_REPLY
-{
-    U16             FunctionDependent1;         /* 0x00 */
-    U8              MsgLength;                  /* 0x02 */
-    U8              Function;                   /* 0x03 */
-    U16             FunctionDependent2;         /* 0x04 */
-    U8              FunctionDependent3;         /* 0x06 */
-    U8              MsgFlags;                   /* 0x07 */
-    U8              VP_ID;                      /* 0x08 */
-    U8              VF_ID;                      /* 0x09 */
-    U16             Reserved1;                  /* 0x0A */
-    U16             FunctionDependent5;         /* 0x0C */
-    U16             IOCStatus;                  /* 0x0E */
-    U32             IOCLogInfo;                 /* 0x10 */
-} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY,
-  MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t;
-
-
-/* common version structure/union used in messages and configuration pages */
-
-typedef struct _MPI2_VERSION_STRUCT
-{
-    U8                      Dev;                        /* 0x00 */
-    U8                      Unit;                       /* 0x01 */
-    U8                      Minor;                      /* 0x02 */
-    U8                      Major;                      /* 0x03 */
-} MPI2_VERSION_STRUCT;
-
-typedef union _MPI2_VERSION_UNION
-{
-    MPI2_VERSION_STRUCT     Struct;
-    U32                     Word;
-} MPI2_VERSION_UNION;
-
-
-/* LUN field defines, common to many structures */
-#define MPI2_LUN_FIRST_LEVEL_ADDRESSING             (0x0000FFFF)
-#define MPI2_LUN_SECOND_LEVEL_ADDRESSING            (0xFFFF0000)
-#define MPI2_LUN_THIRD_LEVEL_ADDRESSING             (0x0000FFFF)
-#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING            (0xFFFF0000)
-#define MPI2_LUN_LEVEL_1_WORD                       (0xFF00)
-#define MPI2_LUN_LEVEL_1_DWORD                      (0x0000FF00)
-
-
-/*****************************************************************************
-*
-*        Fusion-MPT MPI Scatter Gather Elements
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  MPI Simple Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_SIMPLE32
-{
-    U32                     FlagsLength;
-    U32                     Address;
-} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32,
-  Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t;
-
-typedef struct _MPI2_SGE_SIMPLE64
-{
-    U32                     FlagsLength;
-    U64                     Address;
-} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64,
-  Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t;
-
-typedef struct _MPI2_SGE_SIMPLE_UNION
-{
-    U32                     FlagsLength;
-    union
-    {
-        U32                 Address32;
-        U64                 Address64;
-    } u;
-} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
-  Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
-
-
-/****************************************************************************
-*  MPI Chain Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_CHAIN32
-{
-    U16                     Length;
-    U8                      NextChainOffset;
-    U8                      Flags;
-    U32                     Address;
-} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32,
-  Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t;
-
-typedef struct _MPI2_SGE_CHAIN64
-{
-    U16                     Length;
-    U8                      NextChainOffset;
-    U8                      Flags;
-    U64                     Address;
-} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64,
-  Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t;
-
-typedef struct _MPI2_SGE_CHAIN_UNION
-{
-    U16                     Length;
-    U8                      NextChainOffset;
-    U8                      Flags;
-    union
-    {
-        U32                 Address32;
-        U64                 Address64;
-    } u;
-} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
-  Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
-
-
-/****************************************************************************
-*  MPI Transaction Context Element structures
-****************************************************************************/
-
-typedef struct _MPI2_SGE_TRANSACTION32
-{
-    U8                      Reserved;
-    U8                      ContextSize;
-    U8                      DetailsLength;
-    U8                      Flags;
-    U32                     TransactionContext[1];
-    U32                     TransactionDetails[1];
-} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32,
-  Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t;
-
-typedef struct _MPI2_SGE_TRANSACTION64
-{
-    U8                      Reserved;
-    U8                      ContextSize;
-    U8                      DetailsLength;
-    U8                      Flags;
-    U32                     TransactionContext[2];
-    U32                     TransactionDetails[1];
-} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64,
-  Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t;
-
-typedef struct _MPI2_SGE_TRANSACTION96
-{
-    U8                      Reserved;
-    U8                      ContextSize;
-    U8                      DetailsLength;
-    U8                      Flags;
-    U32                     TransactionContext[3];
-    U32                     TransactionDetails[1];
-} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96,
-  Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t;
-
-typedef struct _MPI2_SGE_TRANSACTION128
-{
-    U8                      Reserved;
-    U8                      ContextSize;
-    U8                      DetailsLength;
-    U8                      Flags;
-    U32                     TransactionContext[4];
-    U32                     TransactionDetails[1];
-} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128,
-  Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128;
-
-typedef struct _MPI2_SGE_TRANSACTION_UNION
-{
-    U8                      Reserved;
-    U8                      ContextSize;
-    U8                      DetailsLength;
-    U8                      Flags;
-    union
-    {
-        U32                 TransactionContext32[1];
-        U32                 TransactionContext64[2];
-        U32                 TransactionContext96[3];
-        U32                 TransactionContext128[4];
-    } u;
-    U32                     TransactionDetails[1];
-} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION,
-  Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t;
-
-
-/****************************************************************************
-*  MPI SGE union for IO SGL's
-****************************************************************************/
-
-typedef struct _MPI2_MPI_SGE_IO_UNION
-{
-    union
-    {
-        MPI2_SGE_SIMPLE_UNION   Simple;
-        MPI2_SGE_CHAIN_UNION    Chain;
-    } u;
-} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION,
-  Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t;
-
-
-/****************************************************************************
-*  MPI SGE union for SGL's with Simple and Transaction elements
-****************************************************************************/
-
-typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION
-{
-    union
-    {
-        MPI2_SGE_SIMPLE_UNION       Simple;
-        MPI2_SGE_TRANSACTION_UNION  Transaction;
-    } u;
-} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
-  Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t;
-
-
-/****************************************************************************
-*  All MPI SGE types union
-****************************************************************************/
-
-typedef struct _MPI2_MPI_SGE_UNION
-{
-    union
-    {
-        MPI2_SGE_SIMPLE_UNION       Simple;
-        MPI2_SGE_CHAIN_UNION        Chain;
-        MPI2_SGE_TRANSACTION_UNION  Transaction;
-    } u;
-} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION,
-  Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t;
-
-
-/****************************************************************************
-*  MPI SGE field definition and masks
-****************************************************************************/
-
-/* Flags field bit definitions */
-
-#define MPI2_SGE_FLAGS_LAST_ELEMENT             (0x80)
-#define MPI2_SGE_FLAGS_END_OF_BUFFER            (0x40)
-#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK        (0x30)
-#define MPI2_SGE_FLAGS_LOCAL_ADDRESS            (0x08)
-#define MPI2_SGE_FLAGS_DIRECTION                (0x04)
-#define MPI2_SGE_FLAGS_ADDRESS_SIZE             (0x02)
-#define MPI2_SGE_FLAGS_END_OF_LIST              (0x01)
-
-#define MPI2_SGE_FLAGS_SHIFT                    (24)
-
-#define MPI2_SGE_LENGTH_MASK                    (0x00FFFFFF)
-#define MPI2_SGE_CHAIN_LENGTH_MASK              (0x0000FFFF)
-
-/* Element Type */
-
-#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT      (0x00)
-#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT           (0x10)
-#define MPI2_SGE_FLAGS_CHAIN_ELEMENT            (0x30)
-#define MPI2_SGE_FLAGS_ELEMENT_MASK             (0x30)
-
-/* Address location */
-
-#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS           (0x00)
-
-/* Direction */
-
-#define MPI2_SGE_FLAGS_IOC_TO_HOST              (0x00)
-#define MPI2_SGE_FLAGS_HOST_TO_IOC              (0x04)
-
-#define MPI2_SGE_FLAGS_DEST                     (MPI2_SGE_FLAGS_IOC_TO_HOST)
-#define MPI2_SGE_FLAGS_SOURCE                   (MPI2_SGE_FLAGS_HOST_TO_IOC)
-
-/* Address Size */
-
-#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING        (0x00)
-#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING        (0x02)
-
-/* Context Size */
-
-#define MPI2_SGE_FLAGS_32_BIT_CONTEXT           (0x00)
-#define MPI2_SGE_FLAGS_64_BIT_CONTEXT           (0x02)
-#define MPI2_SGE_FLAGS_96_BIT_CONTEXT           (0x04)
-#define MPI2_SGE_FLAGS_128_BIT_CONTEXT          (0x06)
-
-#define MPI2_SGE_CHAIN_OFFSET_MASK              (0x00FF0000)
-#define MPI2_SGE_CHAIN_OFFSET_SHIFT             (16)
-
-/****************************************************************************
-*  MPI SGE operation Macros
-****************************************************************************/
-
-/* SIMPLE FlagsLength manipulations... */
-#define MPI2_SGE_SET_FLAGS(f)          ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
-#define MPI2_SGE_GET_FLAGS(f)          (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT)
-#define MPI2_SGE_LENGTH(f)             ((f) & MPI2_SGE_LENGTH_MASK)
-#define MPI2_SGE_CHAIN_LENGTH(f)       ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
-
-#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l))
-
-#define MPI2_pSGE_GET_FLAGS(psg)            MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
-#define MPI2_pSGE_GET_LENGTH(psg)           MPI2_SGE_LENGTH((psg)->FlagsLength)
-#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l)
-
-/* CAUTION - The following are READ-MODIFY-WRITE! */
-#define MPI2_pSGE_SET_FLAGS(psg,f)      (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f)
-#define MPI2_pSGE_SET_LENGTH(psg,l)     (psg)->FlagsLength |= MPI2_SGE_LENGTH(l)
-
-#define MPI2_GET_CHAIN_OFFSET(x)    ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT)
-
-
-/*****************************************************************************
-*
-*        Fusion-MPT IEEE Scatter Gather Elements
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  IEEE Simple Element structures
-****************************************************************************/
-
-typedef struct _MPI2_IEEE_SGE_SIMPLE32
-{
-    U32                     Address;
-    U32                     FlagsLength;
-} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
-  Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
-
-typedef struct _MPI2_IEEE_SGE_SIMPLE64
-{
-    U64                     Address;
-    U32                     Length;
-    U16                     Reserved1;
-    U8                      Reserved2;
-    U8                      Flags;
-} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
-  Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
-
-typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
-{
-    MPI2_IEEE_SGE_SIMPLE32  Simple32;
-    MPI2_IEEE_SGE_SIMPLE64  Simple64;
-} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
-  Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
-
-
-/****************************************************************************
-*  IEEE Chain Element structures
-****************************************************************************/
-
-typedef MPI2_IEEE_SGE_SIMPLE32  MPI2_IEEE_SGE_CHAIN32;
-
-typedef MPI2_IEEE_SGE_SIMPLE64  MPI2_IEEE_SGE_CHAIN64;
-
-typedef union _MPI2_IEEE_SGE_CHAIN_UNION
-{
-    MPI2_IEEE_SGE_CHAIN32   Chain32;
-    MPI2_IEEE_SGE_CHAIN64   Chain64;
-} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
-  Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
-
-
-/****************************************************************************
-*  All IEEE SGE types union
-****************************************************************************/
-
-typedef struct _MPI2_IEEE_SGE_UNION
-{
-    union
-    {
-        MPI2_IEEE_SGE_SIMPLE_UNION  Simple;
-        MPI2_IEEE_SGE_CHAIN_UNION   Chain;
-    } u;
-} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION,
-  Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t;
-
-
-/****************************************************************************
-*  IEEE SGE field definitions and masks
-****************************************************************************/
-
-/* Flags field bit definitions */
-
-#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK   (0x80)
-
-#define MPI2_IEEE32_SGE_FLAGS_SHIFT             (24)
-
-#define MPI2_IEEE32_SGE_LENGTH_MASK             (0x00FFFFFF)
-
-/* Element Type */
-
-#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT      (0x00)
-#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT       (0x80)
-
-/* Data Location Address Space */
-
-#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK           (0x03)
-#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR         (0x00)
-                                               /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR         (0x01)
-                                               /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR         (0x02)
-#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR      (0x03)
-                                               /* IEEE Simple Element only */
-#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR   (0x03)
-                                               /* IEEE Chain Element only */
-#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR   \
-       (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) /* typo in name */
-
-/****************************************************************************
-*  IEEE SGE operation Macros
-****************************************************************************/
-
-/* SIMPLE FlagsLength manipulations... */
-#define MPI2_IEEE32_SGE_SET_FLAGS(f)     ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
-#define MPI2_IEEE32_SGE_GET_FLAGS(f)     (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
-#define MPI2_IEEE32_SGE_LENGTH(f)        ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
-
-#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l)      (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l))
-
-#define MPI2_IEEE32_pSGE_GET_FLAGS(psg)             MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
-#define MPI2_IEEE32_pSGE_GET_LENGTH(psg)            MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
-#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l)  (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l)
-
-/* CAUTION - The following are READ-MODIFY-WRITE! */
-#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f)    (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f)
-#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l)   (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l)
-
-
-
-
-/*****************************************************************************
-*
-*        Fusion-MPT MPI/IEEE Scatter Gather Unions
-*
-*****************************************************************************/
-
-typedef union _MPI2_SIMPLE_SGE_UNION
-{
-    MPI2_SGE_SIMPLE_UNION       MpiSimple;
-    MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
-} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION,
-  Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t;
-
-
-typedef union _MPI2_SGE_IO_UNION
-{
-    MPI2_SGE_SIMPLE_UNION       MpiSimple;
-    MPI2_SGE_CHAIN_UNION        MpiChain;
-    MPI2_IEEE_SGE_SIMPLE_UNION  IeeeSimple;
-    MPI2_IEEE_SGE_CHAIN_UNION   IeeeChain;
-} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
-  Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
-
-
-/****************************************************************************
-*
-*  Values for SGLFlags field, used in many request messages with an SGL
-*
-****************************************************************************/
-
-/* values for MPI SGL Data Location Address Space subfield */
-#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK            (0x0C)
-#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE          (0x00)
-#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE          (0x04)
-#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE          (0x08)
-#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE       (0x0C)
-/* values for SGL Type subfield */
-#define MPI2_SGLFLAGS_SGL_TYPE_MASK                 (0x03)
-#define MPI2_SGLFLAGS_SGL_TYPE_MPI                  (0x00)
-#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32               (0x01)
-#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64               (0x02)
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
deleted file mode 100644 (file)
index ee8d2d6..0000000
+++ /dev/null
@@ -1,3068 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_cnfg.h
- *          Title:  MPI Configuration messages and pages
- *  Creation Date:  November 10, 2006
- *
- *    mpi2_cnfg.h Version:  02.00.29
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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 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 SupportedPhysDisks field to RAID Volume Page 1 and
- *                      added related defines.
- *                      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.
- *  07-30-09  02.00.12  Added IO Unit Page 7.
- *                      Added new device ids.
- *                      Added SAS IO Unit Page 5.
- *                      Added partial and slumber power management capable flags
- *                      to SAS Device Page 0 Flags field.
- *                      Added PhyInfo defines for power condition.
- *                      Added Ethernet configuration pages.
- *  10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
- *                      Added SAS PHY Page 4 structure and defines.
- *  02-10-10  02.00.14  Modified the comments for the configuration page
- *                      structures that contain an array of data. The host
- *                      should use the "count" field in the page data (e.g. the
- *                      NumPhys field) to determine the number of valid elements
- *                      in the array.
- *                      Added/modified some MPI2_MFGPAGE_DEVID_SAS defines.
- *                      Added PowerManagementCapabilities to IO Unit Page 7.
- *                      Added PortWidthModGroup field to
- *                      MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS.
- *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines.
- *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines.
- *                      Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines.
- *  05-12-10  02.00.15  Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT
- *                      define.
- *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
- *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
- *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
- *                      defines.
- *  11-10-10  02.00.17  Added ReceptacleID field (replacing Reserved1) to
- *                      MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for
- *                      the Pinout field.
- *                      Added BoardTemperature and BoardTemperatureUnits fields
- *                      to MPI2_CONFIG_PAGE_IO_UNIT_7.
- *                      Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define
- *                      and MPI2_CONFIG_PAGE_EXT_MAN_PS structure.
- *  02-23-11  02.00.18  Added ProxyVF_ID field to MPI2_CONFIG_REQUEST.
- *                      Added IO Unit Page 8, IO Unit Page 9,
- *                      and IO Unit Page 10.
- *                      Added SASNotifyPrimitiveMasks field to
- *                      MPI2_CONFIG_PAGE_IOC_7.
- *  03-09-11  02.00.19  Fixed IO Unit Page 10 (to match the spec).
- *  05-25-11  02.00.20  Cleaned up a few comments.
- *  08-24-11  02.00.21  Marked the IO Unit Page 7 PowerManagementCapabilities
- *                      for PCIe link as obsolete.
- *                      Added SpinupFlags field containing a Disable Spin-up
- *                      bit to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of
- *                      SAS IO Unit Page 4.
- *  11-18-11  02.00.22  Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT.
- *                      Added UEFIVersion field to BIOS Page 1 and defined new
- *                      BiosOptions bits.
- *  11-27-12  02.00.23  Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER.
- *                     Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID.
- *  12-20-12  02.00.24  Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as
- *                     obsolete for MPI v2.5 and later.
- *                     Added some defines for 12G SAS speeds.
- *  04-09-13  02.00.25  Added MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK.
- *                     Fixed MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS to
- *                     match the specification.
- *  12-05-13  02.00.27  Added MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL for
- *                     MPI2_CONFIG_PAGE_MAN_7.
- *                     Added EnclosureLevel and ConnectorName fields to
- *                     MPI2_CONFIG_PAGE_SAS_DEV_0.
- *                     Added MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID for
- *                     MPI2_CONFIG_PAGE_SAS_DEV_0.
- *                     Added EnclosureLevel field to
- *                     MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- *                     Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for
- *                     MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- *  01-08-14  02.00.28  Added more defines for the BiosOptions field of
- *                     MPI2_CONFIG_PAGE_BIOS_1.
- *  06-13-14  02.00.29  Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and
- *                     more defines for the BiosOptions field.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_CNFG_H
-#define MPI2_CNFG_H
-
-/*****************************************************************************
-*   Configuration Page Header and defines
-*****************************************************************************/
-
-/* Config Page Header */
-typedef struct _MPI2_CONFIG_PAGE_HEADER
-{
-    U8                 PageVersion;                /* 0x00 */
-    U8                 PageLength;                 /* 0x01 */
-    U8                 PageNumber;                 /* 0x02 */
-    U8                 PageType;                   /* 0x03 */
-} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER,
-  Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t;
-
-typedef union _MPI2_CONFIG_PAGE_HEADER_UNION
-{
-   MPI2_CONFIG_PAGE_HEADER  Struct;
-   U8                       Bytes[4];
-   U16                      Word16[2];
-   U32                      Word32;
-} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
-  Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion;
-
-/* Extended Config Page Header */
-typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER
-{
-    U8                  PageVersion;                /* 0x00 */
-    U8                  Reserved1;                  /* 0x01 */
-    U8                  PageNumber;                 /* 0x02 */
-    U8                  PageType;                   /* 0x03 */
-    U16                 ExtPageLength;              /* 0x04 */
-    U8                  ExtPageType;                /* 0x06 */
-    U8                  Reserved2;                  /* 0x07 */
-} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
-  MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
-  Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t;
-
-typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
-{
-   MPI2_CONFIG_PAGE_HEADER          Struct;
-   MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
-   U8                               Bytes[8];
-   U16                              Word16[4];
-   U32                              Word32[2];
-} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
-  Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion;
-
-
-/* PageType field values */
-#define MPI2_CONFIG_PAGEATTR_READ_ONLY              (0x00)
-#define MPI2_CONFIG_PAGEATTR_CHANGEABLE             (0x10)
-#define MPI2_CONFIG_PAGEATTR_PERSISTENT             (0x20)
-#define MPI2_CONFIG_PAGEATTR_MASK                   (0xF0)
-
-#define MPI2_CONFIG_PAGETYPE_IO_UNIT                (0x00)
-#define MPI2_CONFIG_PAGETYPE_IOC                    (0x01)
-#define MPI2_CONFIG_PAGETYPE_BIOS                   (0x02)
-#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME            (0x08)
-#define MPI2_CONFIG_PAGETYPE_MANUFACTURING          (0x09)
-#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK          (0x0A)
-#define MPI2_CONFIG_PAGETYPE_EXTENDED               (0x0F)
-#define MPI2_CONFIG_PAGETYPE_MASK                   (0x0F)
-
-#define MPI2_CONFIG_TYPENUM_MASK                    (0x0FFF)
-
-
-/* ExtPageType field values */
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT         (0x10)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER        (0x11)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE          (0x12)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY             (0x13)
-#define MPI2_CONFIG_EXTPAGETYPE_LOG                 (0x14)
-#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE           (0x15)
-#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG         (0x16)
-#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      (0x17)
-#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            (0x18)
-#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET            (0x19)
-#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING   (0x1A)
-
-
-/*****************************************************************************
-*   PageAddress defines
-*****************************************************************************/
-
-/* RAID Volume PageAddress format */
-#define MPI2_RAID_VOLUME_PGAD_FORM_MASK             (0xF0000000)
-#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE  (0x00000000)
-#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE           (0x10000000)
-
-#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK           (0x0000FFFF)
-
-
-/* RAID Physical Disk PageAddress format */
-#define MPI2_PHYSDISK_PGAD_FORM_MASK                    (0xF0000000)
-#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM    (0x00000000)
-#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM             (0x10000000)
-#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE               (0x20000000)
-
-#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK             (0x000000FF)
-#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK               (0x0000FFFF)
-
-
-/* SAS Expander PageAddress format */
-#define MPI2_SAS_EXPAND_PGAD_FORM_MASK              (0xF0000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL     (0x00000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM      (0x10000000)
-#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL              (0x20000000)
-
-#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK            (0x0000FFFF)
-#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK            (0x00FF0000)
-#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT           (16)
-
-
-/* SAS Device PageAddress format */
-#define MPI2_SAS_DEVICE_PGAD_FORM_MASK              (0xF0000000)
-#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
-#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE            (0x20000000)
-
-#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK            (0x0000FFFF)
-
-
-/* SAS PHY PageAddress format */
-#define MPI2_SAS_PHY_PGAD_FORM_MASK                 (0xF0000000)
-#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER           (0x00000000)
-#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX        (0x10000000)
-
-#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK           (0x000000FF)
-#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK        (0x0000FFFF)
-
-
-/* SAS Port PageAddress format */
-#define MPI2_SASPORT_PGAD_FORM_MASK                 (0xF0000000)
-#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT        (0x00000000)
-#define MPI2_SASPORT_PGAD_FORM_PORT_NUM             (0x10000000)
-
-#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK           (0x00000FFF)
-
-
-/* SAS Enclosure PageAddress format */
-#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK              (0xF0000000)
-#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE   (0x00000000)
-#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE            (0x10000000)
-
-#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK            (0x0000FFFF)
-
-
-/* RAID Configuration PageAddress format */
-#define MPI2_RAID_PGAD_FORM_MASK                    (0xF0000000)
-#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM      (0x00000000)
-#define MPI2_RAID_PGAD_FORM_CONFIGNUM               (0x10000000)
-#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG           (0x20000000)
-
-#define MPI2_RAID_PGAD_CONFIGNUM_MASK               (0x000000FF)
-
-
-/* Driver Persistent Mapping PageAddress format */
-#define MPI2_DPM_PGAD_FORM_MASK                     (0xF0000000)
-#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE              (0x00000000)
-
-#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK              (0x0FFF0000)
-#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT             (16)
-#define MPI2_DPM_PGAD_START_ENTRY_MASK              (0x0000FFFF)
-
-
-/* Ethernet PageAddress format */
-#define MPI2_ETHERNET_PGAD_FORM_MASK                (0xF0000000)
-#define MPI2_ETHERNET_PGAD_FORM_IF_NUM              (0x00000000)
-
-#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK           (0x000000FF)
-
-
-
-/****************************************************************************
-*   Configuration messages
-****************************************************************************/
-
-/* Configuration Request Message */
-typedef struct _MPI2_CONFIG_REQUEST
-{
-    U8                      Action;                     /* 0x00 */
-    U8                      SGLFlags;                   /* 0x01 */
-    U8                      ChainOffset;                /* 0x02 */
-    U8                      Function;                   /* 0x03 */
-    U16                     ExtPageLength;              /* 0x04 */
-    U8                      ExtPageType;                /* 0x06 */
-    U8                      MsgFlags;                   /* 0x07 */
-    U8                      VP_ID;                      /* 0x08 */
-    U8                      VF_ID;                      /* 0x09 */
-    U16                     Reserved1;                  /* 0x0A */
-       U8                      Reserved2;                  /* 0x0C */
-       U8                      ProxyVF_ID;                 /* 0x0D */
-       U16                     Reserved4;                  /* 0x0E */
-    U32                     Reserved3;                  /* 0x10 */
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x14 */
-    U32                     PageAddress;                /* 0x18 */
-    MPI2_SGE_IO_UNION       PageBufferSGE;              /* 0x1C */
-} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST,
-  Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t;
-
-/* values for the Action field */
-#define MPI2_CONFIG_ACTION_PAGE_HEADER              (0x00)
-#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT        (0x01)
-#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT       (0x02)
-#define MPI2_CONFIG_ACTION_PAGE_DEFAULT             (0x03)
-#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM         (0x04)
-#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT        (0x05)
-#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM          (0x06)
-#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE      (0x07)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* Config Reply Message */
-typedef struct _MPI2_CONFIG_REPLY
-{
-    U8                      Action;                     /* 0x00 */
-    U8                      SGLFlags;                   /* 0x01 */
-    U8                      MsgLength;                  /* 0x02 */
-    U8                      Function;                   /* 0x03 */
-    U16                     ExtPageLength;              /* 0x04 */
-    U8                      ExtPageType;                /* 0x06 */
-    U8                      MsgFlags;                   /* 0x07 */
-    U8                      VP_ID;                      /* 0x08 */
-    U8                      VF_ID;                      /* 0x09 */
-    U16                     Reserved1;                  /* 0x0A */
-    U16                     Reserved2;                  /* 0x0C */
-    U16                     IOCStatus;                  /* 0x0E */
-    U32                     IOCLogInfo;                 /* 0x10 */
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x14 */
-} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY,
-  Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t;
-
-
-
-/*****************************************************************************
-*
-*               C o n f i g u r a t i o n    P a g e s
-*
-*****************************************************************************/
-
-/****************************************************************************
-*   Manufacturing Config pages
-****************************************************************************/
-
-#define MPI2_MFGPAGE_VENDORID_LSI                   (0x1000)
-
-/* SAS */
-#define MPI2_MFGPAGE_DEVID_SAS2004                  (0x0070)
-#define MPI2_MFGPAGE_DEVID_SAS2008                  (0x0072)
-#define MPI2_MFGPAGE_DEVID_SAS2108_1                (0x0074)
-#define MPI2_MFGPAGE_DEVID_SAS2108_2                (0x0076)
-#define MPI2_MFGPAGE_DEVID_SAS2108_3                (0x0077)
-#define MPI2_MFGPAGE_DEVID_SAS2116_1                (0x0064)
-#define MPI2_MFGPAGE_DEVID_SAS2116_2                (0x0065)
-
-#define MPI2_MFGPAGE_DEVID_SSS6200                  (0x007E)
-
-#define MPI2_MFGPAGE_DEVID_SAS2208_1                (0x0080)
-#define MPI2_MFGPAGE_DEVID_SAS2208_2                (0x0081)
-#define MPI2_MFGPAGE_DEVID_SAS2208_3                (0x0082)
-#define MPI2_MFGPAGE_DEVID_SAS2208_4                (0x0083)
-#define MPI2_MFGPAGE_DEVID_SAS2208_5                (0x0084)
-#define MPI2_MFGPAGE_DEVID_SAS2208_6                (0x0085)
-#define MPI2_MFGPAGE_DEVID_SAS2308_1                (0x0086)
-#define MPI2_MFGPAGE_DEVID_SAS2308_2                (0x0087)
-#define MPI2_MFGPAGE_DEVID_SAS2308_3                (0x006E)
-
-
-
-
-/* Manufacturing Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_0
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U8                      ChipName[16];               /* 0x04 */
-    U8                      ChipRevision[8];            /* 0x14 */
-    U8                      BoardName[16];              /* 0x1C */
-    U8                      BoardAssembly[16];          /* 0x2C */
-    U8                      BoardTracerNumber[16];      /* 0x3C */
-} MPI2_CONFIG_PAGE_MAN_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0,
-  Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t;
-
-#define MPI2_MANUFACTURING0_PAGEVERSION                (0x00)
-
-
-/* Manufacturing Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_1
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U8                      VPD[256];                   /* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_1,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1,
-  Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t;
-
-#define MPI2_MANUFACTURING1_PAGEVERSION                (0x00)
-
-
-typedef struct _MPI2_CHIP_REVISION_ID
-{
-    U16 DeviceID;                                       /* 0x00 */
-    U8  PCIRevisionID;                                  /* 0x02 */
-    U8  Reserved;                                       /* 0x03 */
-} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID,
-  Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t;
-
-
-/* Manufacturing Page 2 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check Header.PageLength at runtime.
- */
-#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
-#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS   (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_2
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    MPI2_CHIP_REVISION_ID   ChipId;                     /* 0x04 */
-    U32                     HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_2,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2,
-  Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t;
-
-#define MPI2_MANUFACTURING2_PAGEVERSION                 (0x00)
-
-
-/* Manufacturing Page 3 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check Header.PageLength at runtime.
- */
-#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
-#define MPI2_MAN_PAGE_3_INFO_WORDS          (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_3
-{
-    MPI2_CONFIG_PAGE_HEADER             Header;         /* 0x00 */
-    MPI2_CHIP_REVISION_ID               ChipId;         /* 0x04 */
-    U32                                 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_3,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3,
-  Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t;
-
-#define MPI2_MANUFACTURING3_PAGEVERSION                 (0x00)
-
-
-/* Manufacturing Page 4 */
-
-typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS
-{
-    U8                          PowerSaveFlags;                 /* 0x00 */
-    U8                          InternalOperationsSleepTime;    /* 0x01 */
-    U8                          InternalOperationsRunTime;      /* 0x02 */
-    U8                          HostIdleTime;                   /* 0x03 */
-} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
-  MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
-  Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t;
-
-/* defines for the PowerSaveFlags field */
-#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE               (0x03)
-#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED           (0x00)
-#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE             (0x01)
-#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE               (0x02)
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_4
-{
-    MPI2_CONFIG_PAGE_HEADER             Header;                 /* 0x00 */
-    U32                                 Reserved1;              /* 0x04 */
-    U32                                 Flags;                  /* 0x08 */
-    U8                                  InquirySize;            /* 0x0C */
-    U8                                  Reserved2;              /* 0x0D */
-    U16                                 Reserved3;              /* 0x0E */
-    U8                                  InquiryData[56];        /* 0x10 */
-    U32                                 RAID0VolumeSettings;    /* 0x48 */
-    U32                                 RAID1EVolumeSettings;   /* 0x4C */
-    U32                                 RAID1VolumeSettings;    /* 0x50 */
-    U32                                 RAID10VolumeSettings;   /* 0x54 */
-    U32                                 Reserved4;              /* 0x58 */
-    U32                                 Reserved5;              /* 0x5C */
-    MPI2_MANPAGE4_PWR_SAVE_SETTINGS     PowerSaveSettings;      /* 0x60 */
-    U8                                  MaxOCEDisks;            /* 0x64 */
-    U8                                  ResyncRate;             /* 0x65 */
-    U16                                 DataScrubDuration;      /* 0x66 */
-    U8                                  MaxHotSpares;           /* 0x68 */
-    U8                                  MaxPhysDisksPerVol;     /* 0x69 */
-    U8                                  MaxPhysDisks;           /* 0x6A */
-    U8                                  MaxVolumes;             /* 0x6B */
-} MPI2_CONFIG_PAGE_MAN_4,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4,
-  Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t;
-
-#define MPI2_MANUFACTURING4_PAGEVERSION                 (0x0A)
-
-/* Manufacturing Page 4 Flags field */
-#define MPI2_MANPAGE4_METADATA_SIZE_MASK                (0x00030000)
-#define MPI2_MANPAGE4_METADATA_512MB                    (0x00000000)
-
-#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA                  (0x00008000)
-#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD               (0x00004000)
-#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR              (0x00002000)
-
-#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION            (0x00001C00)
-#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB             (0x00000000)
-#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION           (0x00000400)
-#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION        (0x00000800)
-#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION            (0x00000C00)
-
-#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING            (0x00000300)
-#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING         (0x00000000)
-#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING           (0x00000100)
-#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING      (0x00000200)
-
-#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER            (0x00000080)
-#define MPI2_MANPAGE4_RAID10_DISABLE                    (0x00000040)
-#define MPI2_MANPAGE4_RAID1E_DISABLE                    (0x00000020)
-#define MPI2_MANPAGE4_RAID1_DISABLE                     (0x00000010)
-#define MPI2_MANPAGE4_RAID0_DISABLE                     (0x00000008)
-#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE              (0x00000004)
-#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE            (0x00000002)
-#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA                (0x00000001)
-
-
-/* Manufacturing Page 5 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
-#define MPI2_MAN_PAGE_5_PHY_ENTRIES         (1)
-#endif
-
-typedef struct _MPI2_MANUFACTURING5_ENTRY
-{
-    U64                                 WWID;           /* 0x00 */
-    U64                                 DeviceName;     /* 0x08 */
-} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY,
-  Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_5
-{
-    MPI2_CONFIG_PAGE_HEADER             Header;         /* 0x00 */
-    U8                                  NumPhys;        /* 0x04 */
-    U8                                  Reserved1;      /* 0x05 */
-    U16                                 Reserved2;      /* 0x06 */
-    U32                                 Reserved3;      /* 0x08 */
-    U32                                 Reserved4;      /* 0x0C */
-    MPI2_MANUFACTURING5_ENTRY           Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */
-} MPI2_CONFIG_PAGE_MAN_5,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5,
-  Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t;
-
-#define MPI2_MANUFACTURING5_PAGEVERSION                 (0x03)
-
-
-/* Manufacturing Page 6 */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_6
-{
-    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
-    U32                             ProductSpecificInfo;/* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_6,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6,
-  Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t;
-
-#define MPI2_MANUFACTURING6_PAGEVERSION                 (0x00)
-
-
-/* Manufacturing Page 7 */
-
-typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
-{
-    U32                         Pinout;                 /* 0x00 */
-    U8                          Connector[16];          /* 0x04 */
-    U8                          Location;               /* 0x14 */
-       U8                          ReceptacleID;           /* 0x15 */
-    U16                         Slot;                   /* 0x16 */
-    U32                         Reserved2;              /* 0x18 */
-} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
-  Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
-
-/* defines for the Pinout field */
-#define MPI2_MANPAGE7_PINOUT_LANE_MASK                  (0x0000FF00)
-#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT                 (8)
-
-#define MPI2_MANPAGE7_PINOUT_TYPE_MASK                  (0x000000FF)
-#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN               (0x00)
-#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE                (0x01)
-#define MPI2_MANPAGE7_PINOUT_SFF_8482                   (0x02)
-#define MPI2_MANPAGE7_PINOUT_SFF_8486                   (0x03)
-#define MPI2_MANPAGE7_PINOUT_SFF_8484                   (0x04)
-#define MPI2_MANPAGE7_PINOUT_SFF_8087                   (0x05)
-#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I                (0x06)
-#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I                (0x07)
-#define MPI2_MANPAGE7_PINOUT_SFF_8470                   (0x08)
-#define MPI2_MANPAGE7_PINOUT_SFF_8088                   (0x09)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X                (0x0A)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X                (0x0B)
-#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X               (0x0C)
-#define MPI2_MANPAGE7_PINOUT_SFF_8436                   (0x0D)
-
-/* defines for the Location field */
-#define MPI2_MANPAGE7_LOCATION_UNKNOWN                  (0x01)
-#define MPI2_MANPAGE7_LOCATION_INTERNAL                 (0x02)
-#define MPI2_MANPAGE7_LOCATION_EXTERNAL                 (0x04)
-#define MPI2_MANPAGE7_LOCATION_SWITCHABLE               (0x08)
-#define MPI2_MANPAGE7_LOCATION_AUTO                     (0x10)
-#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT              (0x20)
-#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED            (0x80)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
-#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX  (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_7
-{
-    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
-    U32                             Reserved1;          /* 0x04 */
-    U32                             Reserved2;          /* 0x08 */
-    U32                             Flags;              /* 0x0C */
-    U8                              EnclosureName[16];  /* 0x10 */
-    U8                              NumPhys;            /* 0x20 */
-    U8                              Reserved3;          /* 0x21 */
-    U16                             Reserved4;          /* 0x22 */
-    MPI2_MANPAGE7_CONNECTOR_INFO    ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */
-} MPI2_CONFIG_PAGE_MAN_7,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
-  Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
-
-#define MPI2_MANUFACTURING7_PAGEVERSION                 (0x01)
-
-/* defines for the Flags field */
-#define MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL         (0x00000008)
-#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER       (0x00000002)
-#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO                (0x00000001)
-
-
-/*
- * Generic structure to use for product-specific manufacturing pages
- * (currently Manufacturing Page 8 through Manufacturing Page 31).
- */
-
-typedef struct _MPI2_CONFIG_PAGE_MAN_PS
-{
-    MPI2_CONFIG_PAGE_HEADER         Header;             /* 0x00 */
-    U32                             ProductSpecificInfo;/* 0x04 */
-} MPI2_CONFIG_PAGE_MAN_PS,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS,
-  Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t;
-
-#define MPI2_MANUFACTURING8_PAGEVERSION                 (0x00)
-#define MPI2_MANUFACTURING9_PAGEVERSION                 (0x00)
-#define MPI2_MANUFACTURING10_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING11_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING12_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING13_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING14_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING15_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING16_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING17_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING18_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING19_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING20_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING21_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING22_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING23_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING24_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING25_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING26_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING27_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING28_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING29_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING30_PAGEVERSION                (0x00)
-#define MPI2_MANUFACTURING31_PAGEVERSION                (0x00)
-
-
-/****************************************************************************
-*   IO Unit Config Pages
-****************************************************************************/
-
-/* IO Unit Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U64                     UniqueValue;                /* 0x04 */
-    MPI2_VERSION_UNION      NvdataVersionDefault;       /* 0x08 */
-    MPI2_VERSION_UNION      NvdataVersionPersistent;    /* 0x0A */
-} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
-  Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t;
-
-#define MPI2_IOUNITPAGE0_PAGEVERSION                    (0x02)
-
-
-/* IO Unit Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U32                     Flags;                      /* 0x04 */
-} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
-  Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t;
-
-#define MPI2_IOUNITPAGE1_PAGEVERSION                    (0x04)
-
-/* IO Unit Page 1 Flags defines */
-#define MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK       (0x00004000)
-#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY    (0x00000800)
-#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE          (0x00000600)
-#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT         (9)
-#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE        (0x00000000)
-#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE       (0x00000200)
-#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE     (0x00000400)
-#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE       (0x00000100)
-#define MPI2_IOUNITPAGE1_DISABLE_IR                     (0x00000040)
-#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
-#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID        (0x00000004)
-
-
-/* IO Unit Page 3 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for GPIOCount at runtime.
- */
-#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
-#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX    (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                                   /* 0x00 */
-    U8                      GPIOCount;                                /* 0x04 */
-    U8                      Reserved1;                                /* 0x05 */
-    U16                     Reserved2;                                /* 0x06 */
-    U16                     GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */
-} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
-  Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t;
-
-#define MPI2_IOUNITPAGE3_PAGEVERSION                    (0x01)
-
-/* defines for IO Unit Page 3 GPIOVal field */
-#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK             (0xFFFC)
-#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT            (2)
-#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF               (0x0000)
-#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 the value returned for 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      (0xFFFF0000)
-#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)
-
-
-/* IO Unit Page 7 */
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
-    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 0x00 */
-    U16                     Reserved1;                              /* 0x04 */
-    U8                      PCIeWidth;                              /* 0x06 */
-    U8                      PCIeSpeed;                              /* 0x07 */
-    U32                     ProcessorState;                         /* 0x08 */
-    U32                     PowerManagementCapabilities;            /* 0x0C */
-    U16                     IOCTemperature;                         /* 0x10 */
-    U8                      IOCTemperatureUnits;                    /* 0x12 */
-    U8                      IOCSpeed;                               /* 0x13 */
-       U16                     BoardTemperature;                   /* 0x14 */
-       U8                      BoardTemperatureUnits;              /* 0x16 */
-       U8                      Reserved3;                          /* 0x17 */
-       U32                     Reserved4;                          /* 0x18 */
-       U32                     Reserved5;                          /* 0x1C */
-       U32                     Reserved6;                          /* 0x20 */
-       U32                     Reserved7;                          /* 0x24 */
-} MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7,
-  Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t;
-
-#define MPI2_IOUNITPAGE7_PAGEVERSION                    (0x04)
-
-/* defines for IO Unit Page 7 PCIeWidth field */
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1              (0x01)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2              (0x02)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4              (0x04)
-#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8              (0x08)
-
-/* defines for IO Unit Page 7 PCIeSpeed field */
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS        (0x00)
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS        (0x01)
-#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS        (0x02)
-
-/* defines for IO Unit Page 7 ProcessorState field */
-#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND         (0x0000000F)
-#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND        (0)
-
-#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT         (0x00)
-#define MPI2_IOUNITPAGE7_PSTATE_DISABLED            (0x01)
-#define MPI2_IOUNITPAGE7_PSTATE_ENABLED             (0x02)
-
-/* defines for IO Unit Page 7 PowerManagementCapabilities field */
-#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED    (0x00000400)
-#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED    (0x00000200)
-#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED    (0x00000100)
-#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE    (0x00000008) /* obsolete */
-#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE    (0x00000004) /* obsolete */
-
-/* defines for IO Unit Page 7 IOCTemperatureUnits field */
-#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT       (0x00)
-#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT        (0x01)
-#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS           (0x02)
-
-/* defines for IO Unit Page 7 IOCSpeed field */
-#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL             (0x01)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF             (0x02)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER          (0x04)
-#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH           (0x08)
-
-/* defines for IO Unit Page 7 BoardTemperatureUnits field */
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT     (0x00)
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT      (0x01)
-#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS         (0x02)
-
-/* IO Unit Page 8 */
-
-#define MPI2_IOUNIT8_NUM_THRESHOLDS     (4)
-
-typedef struct _MPI2_IOUNIT8_SENSOR {
-       U16                     Flags;                /* 0x00 */
-       U16                     Reserved1;            /* 0x02 */
-       U16
-               Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /* 0x04 */
-       U32                     Reserved2;            /* 0x0C */
-       U32                     Reserved3;            /* 0x10 */
-       U32                     Reserved4;            /* 0x14 */
-} MPI2_IOUNIT8_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT8_SENSOR,
-Mpi2IOUnit8Sensor_t, MPI2_POINTER pMpi2IOUnit8Sensor_t;
-
-/* defines for IO Unit Page 8 Sensor Flags field */
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE         (0x0008)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE         (0x0004)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE         (0x0002)
-#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE         (0x0001)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumSensors at runtime.
- */
-#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES     (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 {
-       MPI2_CONFIG_PAGE_HEADER Header;               /* 0x00 */
-       U32                     Reserved1;            /* 0x04 */
-       U32                     Reserved2;            /* 0x08 */
-       U8                      NumSensors;           /* 0x0C */
-       U8                      PollingInterval;      /* 0x0D */
-       U16                     Reserved3;            /* 0x0E */
-       MPI2_IOUNIT8_SENSOR
-                       Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_8,
-Mpi2IOUnitPage8_t, MPI2_POINTER pMpi2IOUnitPage8_t;
-
-#define MPI2_IOUNITPAGE8_PAGEVERSION                    (0x00)
-
-
-/* IO Unit Page 9 */
-
-typedef struct _MPI2_IOUNIT9_SENSOR {
-       U16                     CurrentTemperature;     /* 0x00 */
-       U16                     Reserved1;              /* 0x02 */
-       U8                      Flags;                  /* 0x04 */
-       U8                      Reserved2;              /* 0x05 */
-       U16                     Reserved3;              /* 0x06 */
-       U32                     Reserved4;              /* 0x08 */
-       U32                     Reserved5;              /* 0x0C */
-} MPI2_IOUNIT9_SENSOR, MPI2_POINTER PTR_MPI2_IOUNIT9_SENSOR,
-Mpi2IOUnit9Sensor_t, MPI2_POINTER pMpi2IOUnit9Sensor_t;
-
-/* defines for IO Unit Page 9 Sensor Flags field */
-#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID        (0x01)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumSensors at runtime.
- */
-#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES
-#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES     (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 {
-       MPI2_CONFIG_PAGE_HEADER Header;                /* 0x00 */
-       U32                     Reserved1;             /* 0x04 */
-       U32                     Reserved2;             /* 0x08 */
-       U8                      NumSensors;            /* 0x0C */
-       U8                      Reserved4;             /* 0x0D */
-       U16                     Reserved3;             /* 0x0E */
-       MPI2_IOUNIT9_SENSOR
-                       Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_9, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_9,
-Mpi2IOUnitPage9_t, MPI2_POINTER pMpi2IOUnitPage9_t;
-
-#define MPI2_IOUNITPAGE9_PAGEVERSION                    (0x00)
-
-
-/* IO Unit Page 10 */
-
-typedef struct _MPI2_IOUNIT10_FUNCTION {
-       U8                      CreditPercent;      /* 0x00 */
-       U8                      Reserved1;          /* 0x01 */
-       U16                     Reserved2;          /* 0x02 */
-} MPI2_IOUNIT10_FUNCTION, MPI2_POINTER PTR_MPI2_IOUNIT10_FUNCTION,
-Mpi2IOUnit10Function_t, MPI2_POINTER pMpi2IOUnit10Function_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumFunctions at runtime.
- */
-#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES
-#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES      (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
-       MPI2_CONFIG_PAGE_HEADER Header;                    /* 0x00 */
-       U8                      NumFunctions;             /* 0x04 */
-       U8                      Reserved1;              /* 0x05 */
-       U16                     Reserved2;              /* 0x06 */
-       U32                     Reserved3;              /* 0x08 */
-       U32                     Reserved4;              /* 0x0C */
-       MPI2_IOUNIT10_FUNCTION
-               Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/* 0x10 */
-} MPI2_CONFIG_PAGE_IO_UNIT_10, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_10,
-Mpi2IOUnitPage10_t, MPI2_POINTER pMpi2IOUnitPage10_t;
-
-#define MPI2_IOUNITPAGE10_PAGEVERSION                   (0x01)
-
-
-
-/****************************************************************************
-*   IOC Config Pages
-****************************************************************************/
-
-/* IOC Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_0
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U32                     Reserved1;                  /* 0x04 */
-    U32                     Reserved2;                  /* 0x08 */
-    U16                     VendorID;                   /* 0x0C */
-    U16                     DeviceID;                   /* 0x0E */
-    U8                      RevisionID;                 /* 0x10 */
-    U8                      Reserved3;                  /* 0x11 */
-    U16                     Reserved4;                  /* 0x12 */
-    U32                     ClassCode;                  /* 0x14 */
-    U16                     SubsystemVendorID;          /* 0x18 */
-    U16                     SubsystemID;                /* 0x1A */
-} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0,
-  Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t;
-
-#define MPI2_IOCPAGE0_PAGEVERSION                       (0x02)
-
-
-/* IOC Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_1
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U32                     Flags;                      /* 0x04 */
-    U32                     CoalescingTimeout;          /* 0x08 */
-    U8                      CoalescingDepth;            /* 0x0C */
-    U8                      PCISlotNum;                 /* 0x0D */
-    U8                      PCIBusNum;                  /* 0x0E */
-    U8                      PCIDomainSegment;           /* 0x0F */
-    U32                     Reserved1;                  /* 0x10 */
-    U32                     Reserved2;                  /* 0x14 */
-} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1,
-  Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t;
-
-#define MPI2_IOCPAGE1_PAGEVERSION                       (0x05)
-
-/* defines for IOC Page 1 Flags field */
-#define MPI2_IOCPAGE1_REPLY_COALESCING                  (0x00000001)
-
-#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN                (0xFF)
-#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN                 (0xFF)
-#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN                 (0xFF)
-
-/* IOC Page 6 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_6
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                         /* 0x00 */
-    U32                     CapabilitiesFlags;              /* 0x04 */
-    U8                      MaxDrivesRAID0;                 /* 0x08 */
-    U8                      MaxDrivesRAID1;                 /* 0x09 */
-    U8                      MaxDrivesRAID1E;                /* 0x0A */
-    U8                      MaxDrivesRAID10;                /* 0x0B */
-    U8                      MinDrivesRAID0;                 /* 0x0C */
-    U8                      MinDrivesRAID1;                 /* 0x0D */
-    U8                      MinDrivesRAID1E;                /* 0x0E */
-    U8                      MinDrivesRAID10;                /* 0x0F */
-    U32                     Reserved1;                      /* 0x10 */
-    U8                      MaxGlobalHotSpares;             /* 0x14 */
-    U8                      MaxPhysDisks;                   /* 0x15 */
-    U8                      MaxVolumes;                     /* 0x16 */
-    U8                      MaxConfigs;                     /* 0x17 */
-    U8                      MaxOCEDisks;                    /* 0x18 */
-    U8                      Reserved2;                      /* 0x19 */
-    U16                     Reserved3;                      /* 0x1A */
-    U32                     SupportedStripeSizeMapRAID0;    /* 0x1C */
-    U32                     SupportedStripeSizeMapRAID1E;   /* 0x20 */
-    U32                     SupportedStripeSizeMapRAID10;   /* 0x24 */
-    U32                     Reserved4;                      /* 0x28 */
-    U32                     Reserved5;                      /* 0x2C */
-    U16                     DefaultMetadataSize;            /* 0x30 */
-    U16                     Reserved6;                      /* 0x32 */
-    U16                     MaxBadBlockTableEntries;        /* 0x34 */
-    U16                     Reserved7;                      /* 0x36 */
-    U32                     IRNvsramVersion;                /* 0x38 */
-} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
-  Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
-
-#define MPI2_IOCPAGE6_PAGEVERSION                       (0x05)
-
-/* defines for IOC Page 6 CapabilitiesFlags */
-#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT      (0x00000020)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT          (0x00000010)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT           (0x00000008)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT          (0x00000004)
-#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT           (0x00000002)
-#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE        (0x00000001)
-
-
-/* IOC Page 7 */
-
-#define MPI2_IOCPAGE7_EVENTMASK_WORDS       (4)
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_7
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U32                     Reserved1;                  /* 0x04 */
-    U32                     EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
-    U16                     SASBroadcastPrimitiveMasks; /* 0x18 */
-       U16                     SASNotifyPrimitiveMasks;    /* 0x1A */
-    U32                     Reserved3;                  /* 0x1C */
-} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
-  Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
-
-#define MPI2_IOCPAGE7_PAGEVERSION                       (0x02)
-
-
-/* IOC Page 8 */
-
-typedef struct _MPI2_CONFIG_PAGE_IOC_8
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U8                      NumDevsPerEnclosure;        /* 0x04 */
-    U8                      Reserved1;                  /* 0x05 */
-    U16                     Reserved2;                  /* 0x06 */
-    U16                     MaxPersistentEntries;       /* 0x08 */
-    U16                     MaxNumPhysicalMappedIDs;    /* 0x0A */
-    U16                     Flags;                      /* 0x0C */
-    U16                     Reserved3;                  /* 0x0E */
-    U16                     IRVolumeMappingFlags;       /* 0x10 */
-    U16                     Reserved4;                  /* 0x12 */
-    U32                     Reserved5;                  /* 0x14 */
-} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8,
-  Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t;
-
-#define MPI2_IOCPAGE8_PAGEVERSION                       (0x00)
-
-/* defines for IOC Page 8 Flags field */
-#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1             (0x00000020)
-#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0         (0x00000010)
-
-#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE           (0x0000000E)
-#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING  (0x00000000)
-#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING      (0x00000002)
-
-#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING  (0x00000001)
-#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING   (0x00000000)
-
-/* defines for IOC Page 8 IRVolumeMappingFlags */
-#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE  (0x00000003)
-#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING        (0x00000000)
-#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING       (0x00000001)
-
-
-/****************************************************************************
-*   BIOS Config Pages
-****************************************************************************/
-
-/* BIOS Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_1
-{
-       MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-       U32                     BiosOptions;                /* 0x04 */
-       U32                     IOCSettings;                /* 0x08 */
-       U8                      SSUTimeout;                 /* 0x0C */
-       U8                      Reserved1;                  /* 0x0D */
-       U16                     Reserved2;                  /* 0x0E */
-       U32                     DeviceSettings;             /* 0x10 */
-       U16                     NumberOfDevices;            /* 0x14 */
-       U16                     UEFIVersion;                /* 0x16 */
-       U16                     IOTimeoutBlockDevicesNonRM; /* 0x18 */
-       U16                     IOTimeoutSequential;        /* 0x1A */
-       U16                     IOTimeoutOther;             /* 0x1C */
-       U16                     IOTimeoutBlockDevicesRM;    /* 0x1E */
-} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
-  Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
-
-#define MPI2_BIOSPAGE1_PAGEVERSION                      (0x07)
-
-/* values for BIOS Page 1 BiosOptions field */
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK                        (0x00003800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL                       (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE                  (0x00000800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID                       (0x00001000)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS                       (0x00001800)
-#define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY                       (0x00002000)
-
-#define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS                 (0x00000400)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD       (0x00000300)
-#define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD   (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD       (0x00000100)
-#define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD    (0x00000200)
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD    (0x00000300)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID                  (0x000000F0)
-#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID                   (0x00000000)
-
-#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION   (0x00000006)
-#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII              (0x00000000)
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII             (0x00000002)
-#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII       (0x00000004)
-
-#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS                 (0x00000001)
-
-/* values for BIOS Page 1 IOCSettings field */
-#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE      (0x00030000)
-#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT       (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT          (0x00010000)
-
-#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING           (0x000000C0)
-#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING           (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING           (0x00000040)
-#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING          (0x00000080)
-
-#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT      (0x00000030)
-#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT                (0x00000000)
-#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT              (0x00000010)
-#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT                (0x00000020)
-#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT               (0x00000030)
-
-#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS             (0x00000008)
-
-/* values for BIOS Page 1 DeviceSettings field */
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING     (0x00000010)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN           (0x00000008)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN            (0x00000004)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN        (0x00000002)
-#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN         (0x00000001)
-
-/* defines for BIOS Page 1 UEFIVersion field */
-#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK              (0xFF00)
-#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT             (8)
-#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK              (0x00FF)
-#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT             (0)
-
-
-
-/* BIOS Page 2 */
-
-typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER
-{
-    U32         Reserved1;                              /* 0x00 */
-    U32         Reserved2;                              /* 0x04 */
-    U32         Reserved3;                              /* 0x08 */
-    U32         Reserved4;                              /* 0x0C */
-    U32         Reserved5;                              /* 0x10 */
-    U32         Reserved6;                              /* 0x14 */
-} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
-  MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
-  Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t;
-
-typedef struct _MPI2_BOOT_DEVICE_SAS_WWID
-{
-    U64         SASAddress;                             /* 0x00 */
-    U8          LUN[8];                                 /* 0x08 */
-    U32         Reserved1;                              /* 0x10 */
-    U32         Reserved2;                              /* 0x14 */
-} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID,
-  Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t;
-
-typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT
-{
-    U64         EnclosureLogicalID;                     /* 0x00 */
-    U32         Reserved1;                              /* 0x08 */
-    U32         Reserved2;                              /* 0x0C */
-    U16         SlotNumber;                             /* 0x10 */
-    U16         Reserved3;                              /* 0x12 */
-    U32         Reserved4;                              /* 0x14 */
-} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
-  MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
-  Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t;
-
-typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME
-{
-    U64         DeviceName;                             /* 0x00 */
-    U8          LUN[8];                                 /* 0x08 */
-    U32         Reserved1;                              /* 0x10 */
-    U32         Reserved2;                              /* 0x14 */
-} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
-  Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t;
-
-typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE
-{
-    MPI2_BOOT_DEVICE_ADAPTER_ORDER  AdapterOrder;
-    MPI2_BOOT_DEVICE_SAS_WWID       SasWwid;
-    MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
-    MPI2_BOOT_DEVICE_DEVICE_NAME    DeviceName;
-} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
-  Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t;
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_2
-{
-    MPI2_CONFIG_PAGE_HEADER     Header;                 /* 0x00 */
-    U32                         Reserved1;              /* 0x04 */
-    U32                         Reserved2;              /* 0x08 */
-    U32                         Reserved3;              /* 0x0C */
-    U32                         Reserved4;              /* 0x10 */
-    U32                         Reserved5;              /* 0x14 */
-    U32                         Reserved6;              /* 0x18 */
-    U8                          ReqBootDeviceForm;      /* 0x1C */
-    U8                          Reserved7;              /* 0x1D */
-    U16                         Reserved8;              /* 0x1E */
-    MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedBootDevice;    /* 0x20 */
-    U8                          ReqAltBootDeviceForm;   /* 0x38 */
-    U8                          Reserved9;              /* 0x39 */
-    U16                         Reserved10;             /* 0x3A */
-    MPI2_BIOSPAGE2_BOOT_DEVICE  RequestedAltBootDevice; /* 0x3C */
-    U8                          CurrentBootDeviceForm;  /* 0x58 */
-    U8                          Reserved11;             /* 0x59 */
-    U16                         Reserved12;             /* 0x5A */
-    MPI2_BIOSPAGE2_BOOT_DEVICE  CurrentBootDevice;      /* 0x58 */
-} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2,
-  Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t;
-
-#define MPI2_BIOSPAGE2_PAGEVERSION                      (0x04)
-
-/* values for BIOS Page 2 BootDeviceForm fields */
-#define MPI2_BIOSPAGE2_FORM_MASK                        (0x0F)
-#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED         (0x00)
-#define MPI2_BIOSPAGE2_FORM_SAS_WWID                    (0x05)
-#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT              (0x06)
-#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME                 (0x07)
-
-
-/* BIOS Page 3 */
-
-typedef struct _MPI2_ADAPTER_INFO
-{
-    U8      PciBusNumber;                               /* 0x00 */
-    U8      PciDeviceAndFunctionNumber;                 /* 0x01 */
-    U16     AdapterFlags;                               /* 0x02 */
-} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO,
-  Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t;
-
-#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED                (0x0001)
-#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS             (0x0002)
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_3
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U32                     GlobalFlags;                /* 0x04 */
-    U32                     BiosVersion;                /* 0x08 */
-    MPI2_ADAPTER_INFO       AdapterOrder[4];            /* 0x0C */
-    U32                     Reserved1;                  /* 0x1C */
-} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3,
-  Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t;
-
-#define MPI2_BIOSPAGE3_PAGEVERSION                      (0x00)
-
-/* values for BIOS Page 3 GlobalFlags */
-#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR             (0x00000002)
-#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE             (0x00000004)
-#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE        (0x00000010)
-
-#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK      (0x000000E0)
-#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY      (0x00000000)
-#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY            (0x00000020)
-#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY        (0x00000040)
-
-
-/* BIOS Page 4 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
-#define MPI2_BIOS_PAGE_4_PHY_ENTRIES        (1)
-#endif
-
-typedef struct _MPI2_BIOS4_ENTRY
-{
-    U64                     ReassignmentWWID;       /* 0x00 */
-    U64                     ReassignmentDeviceName; /* 0x08 */
-} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY,
-  Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_BIOS_4
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                             /* 0x00 */
-    U8                      NumPhys;                            /* 0x04 */
-    U8                      Reserved1;                          /* 0x05 */
-    U16                     Reserved2;                          /* 0x06 */
-    MPI2_BIOS4_ENTRY        Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES];  /* 0x08 */
-} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4,
-  Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t;
-
-#define MPI2_BIOSPAGE4_PAGEVERSION                      (0x01)
-
-
-/****************************************************************************
-*   RAID Volume Config Pages
-****************************************************************************/
-
-/* RAID Volume Page 0 */
-
-typedef struct _MPI2_RAIDVOL0_PHYS_DISK
-{
-    U8                      RAIDSetNum;                 /* 0x00 */
-    U8                      PhysDiskMap;                /* 0x01 */
-    U8                      PhysDiskNum;                /* 0x02 */
-    U8                      Reserved;                   /* 0x03 */
-} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK,
-  Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t;
-
-/* defines for the PhysDiskMap field */
-#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY                  (0x01)
-#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY                (0x02)
-
-typedef struct _MPI2_RAIDVOL0_SETTINGS
-{
-    U16                     Settings;                   /* 0x00 */
-    U8                      HotSparePool;               /* 0x01 */
-    U8                      Reserved;                   /* 0x02 */
-} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS,
-  Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t;
-
-/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
-#define MPI2_RAID_HOT_SPARE_POOL_0                      (0x01)
-#define MPI2_RAID_HOT_SPARE_POOL_1                      (0x02)
-#define MPI2_RAID_HOT_SPARE_POOL_2                      (0x04)
-#define MPI2_RAID_HOT_SPARE_POOL_3                      (0x08)
-#define MPI2_RAID_HOT_SPARE_POOL_4                      (0x10)
-#define MPI2_RAID_HOT_SPARE_POOL_5                      (0x20)
-#define MPI2_RAID_HOT_SPARE_POOL_6                      (0x40)
-#define MPI2_RAID_HOT_SPARE_POOL_7                      (0x80)
-
-/* RAID Volume Page 0 VolumeSettings defines */
-#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX     (0x0008)
-#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
-
-#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING        (0x0003)
-#define MPI2_RAIDVOL0_SETTING_UNCHANGED                 (0x0000)
-#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING     (0x0001)
-#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING      (0x0002)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhysDisks at runtime.
- */
-#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
-#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX       (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U16                     DevHandle;                  /* 0x04 */
-    U8                      VolumeState;                /* 0x06 */
-    U8                      VolumeType;                 /* 0x07 */
-    U32                     VolumeStatusFlags;          /* 0x08 */
-    MPI2_RAIDVOL0_SETTINGS  VolumeSettings;             /* 0x0C */
-    U64                     MaxLBA;                     /* 0x10 */
-    U32                     StripeSize;                 /* 0x18 */
-    U16                     BlockSize;                  /* 0x1C */
-    U16                     Reserved1;                  /* 0x1E */
-    U8                      SupportedPhysDisks;         /* 0x20 */
-    U8                      ResyncRate;                 /* 0x21 */
-    U16                     DataScrubDuration;          /* 0x22 */
-    U8                      NumPhysDisks;               /* 0x24 */
-    U8                      Reserved2;                  /* 0x25 */
-    U8                      Reserved3;                  /* 0x26 */
-    U8                      InactiveStatus;             /* 0x27 */
-    MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */
-} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
-  Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t;
-
-#define MPI2_RAIDVOLPAGE0_PAGEVERSION           (0x0A)
-
-/* values for RAID VolumeState */
-#define MPI2_RAID_VOL_STATE_MISSING                         (0x00)
-#define MPI2_RAID_VOL_STATE_FAILED                          (0x01)
-#define MPI2_RAID_VOL_STATE_INITIALIZING                    (0x02)
-#define MPI2_RAID_VOL_STATE_ONLINE                          (0x03)
-#define MPI2_RAID_VOL_STATE_DEGRADED                        (0x04)
-#define MPI2_RAID_VOL_STATE_OPTIMAL                         (0x05)
-
-/* values for RAID VolumeType */
-#define MPI2_RAID_VOL_TYPE_RAID0                            (0x00)
-#define MPI2_RAID_VOL_TYPE_RAID1E                           (0x01)
-#define MPI2_RAID_VOL_TYPE_RAID1                            (0x02)
-#define MPI2_RAID_VOL_TYPE_RAID10                           (0x05)
-#define MPI2_RAID_VOL_TYPE_UNKNOWN                          (0xFF)
-
-/* values for RAID Volume Page 0 VolumeStatusFlags field */
-#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC            (0x02000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING        (0x01000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING               (0x00800000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING      (0x00400000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT      (0x00200000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB                (0x00100000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK         (0x00080000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION        (0x00040000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT           (0x00020000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS        (0x00010000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT        (0x00000080)
-#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED               (0x00000040)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE              (0x00000020)
-#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR          (0x00000000)
-#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR        (0x00000010)
-#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL      (0x00000008)
-#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE           (0x00000004)
-#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED                  (0x00000002)
-#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED                   (0x00000001)
-
-/* values for RAID Volume Page 0 SupportedPhysDisks field */
-#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS             (0x08)
-#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS                    (0x04)
-#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL                  (0x02)
-#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL                 (0x01)
-
-/* values for RAID Volume Page 0 InactiveStatus field */
-#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE                  (0x00)
-#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE           (0x01)
-#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE           (0x02)
-#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE    (0x03)
-#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE             (0x04)
-#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE    (0x05)
-#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED                (0x06)
-
-
-/* RAID Volume Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1
-{
-    MPI2_CONFIG_PAGE_HEADER Header;                     /* 0x00 */
-    U16                     DevHandle;                  /* 0x04 */
-    U16                     Reserved0;                  /* 0x06 */
-    U8                      GUID[24];                   /* 0x08 */
-    U8                      Name[16];                   /* 0x20 */
-    U64                     WWID;                       /* 0x30 */
-    U32                     Reserved1;                  /* 0x38 */
-    U32                     Reserved2;                  /* 0x3C */
-} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
-  Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t;
-
-#define MPI2_RAIDVOLPAGE1_PAGEVERSION           (0x03)
-
-
-/****************************************************************************
-*   RAID Physical Disk Config Pages
-****************************************************************************/
-
-/* RAID Physical Disk Page 0 */
-
-typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS
-{
-    U16                     Reserved1;                  /* 0x00 */
-    U8                      HotSparePool;               /* 0x02 */
-    U8                      Reserved2;                  /* 0x03 */
-} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
-  Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t;
-
-/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
-
-typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA
-{
-    U8                      VendorID[8];                /* 0x00 */
-    U8                      ProductID[16];              /* 0x08 */
-    U8                      ProductRevLevel[4];         /* 0x18 */
-    U8                      SerialNum[32];              /* 0x1C */
-} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
-  MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
-  Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t;
-
-typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
-{
-    MPI2_CONFIG_PAGE_HEADER         Header;                     /* 0x00 */
-    U16                             DevHandle;                  /* 0x04 */
-    U8                              Reserved1;                  /* 0x06 */
-    U8                              PhysDiskNum;                /* 0x07 */
-    MPI2_RAIDPHYSDISK0_SETTINGS     PhysDiskSettings;           /* 0x08 */
-    U32                             Reserved2;                  /* 0x0C */
-    MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData;                /* 0x10 */
-    U32                             Reserved3;                  /* 0x4C */
-    U8                              PhysDiskState;              /* 0x50 */
-    U8                              OfflineReason;              /* 0x51 */
-    U8                              IncompatibleReason;         /* 0x52 */
-    U8                              PhysDiskAttributes;         /* 0x53 */
-    U32                             PhysDiskStatusFlags;        /* 0x54 */
-    U64                             DeviceMaxLBA;               /* 0x58 */
-    U64                             HostMaxLBA;                 /* 0x60 */
-    U64                             CoercedMaxLBA;              /* 0x68 */
-    U16                             BlockSize;                  /* 0x70 */
-    U16                             Reserved5;                  /* 0x72 */
-    U32                             Reserved6;                  /* 0x74 */
-} MPI2_CONFIG_PAGE_RD_PDISK_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
-  Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t;
-
-#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION          (0x05)
-
-/* PhysDiskState defines */
-#define MPI2_RAID_PD_STATE_NOT_CONFIGURED               (0x00)
-#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE               (0x01)
-#define MPI2_RAID_PD_STATE_OFFLINE                      (0x02)
-#define MPI2_RAID_PD_STATE_ONLINE                       (0x03)
-#define MPI2_RAID_PD_STATE_HOT_SPARE                    (0x04)
-#define MPI2_RAID_PD_STATE_DEGRADED                     (0x05)
-#define MPI2_RAID_PD_STATE_REBUILDING                   (0x06)
-#define MPI2_RAID_PD_STATE_OPTIMAL                      (0x07)
-
-/* OfflineReason defines */
-#define MPI2_PHYSDISK0_ONLINE                           (0x00)
-#define MPI2_PHYSDISK0_OFFLINE_MISSING                  (0x01)
-#define MPI2_PHYSDISK0_OFFLINE_FAILED                   (0x03)
-#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING             (0x04)
-#define MPI2_PHYSDISK0_OFFLINE_REQUESTED                (0x05)
-#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED         (0x06)
-#define MPI2_PHYSDISK0_OFFLINE_OTHER                    (0xFF)
-
-/* IncompatibleReason defines */
-#define MPI2_PHYSDISK0_COMPATIBLE                       (0x00)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL            (0x01)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE           (0x02)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA             (0x03)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD   (0x04)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA    (0x05)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE          (0x06)
-#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN             (0xFF)
-
-/* PhysDiskAttributes defines */
-#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK                (0x0C)
-#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE         (0x08)
-#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE           (0x04)
-
-#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK             (0x03)
-#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL              (0x02)
-#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL             (0x01)
-
-/* PhysDiskStatusFlags defines */
-#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED        (0x00000040)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET           (0x00000020)
-#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED  (0x00000010)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS     (0x00000000)
-#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
-#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME      (0x00000004)
-#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED             (0x00000002)
-#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC          (0x00000001)
-
-
-/* RAID Physical Disk Page 1 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhysDiskPaths at runtime.
- */
-#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
-#define MPI2_RAID_PHYS_DISK1_PATH_MAX   (1)
-#endif
-
-typedef struct _MPI2_RAIDPHYSDISK1_PATH
-{
-    U16             DevHandle;          /* 0x00 */
-    U16             Reserved1;          /* 0x02 */
-    U64             WWID;               /* 0x04 */
-    U64             OwnerWWID;          /* 0x0C */
-    U8              OwnerIdentifier;    /* 0x14 */
-    U8              Reserved2;          /* 0x15 */
-    U16             Flags;              /* 0x16 */
-} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH,
-  Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t;
-
-/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
-#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY        (0x0004)
-#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN         (0x0002)
-#define MPI2_RAID_PHYSDISK1_FLAG_INVALID        (0x0001)
-
-typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
-{
-    MPI2_CONFIG_PAGE_HEADER         Header;                     /* 0x00 */
-    U8                              NumPhysDiskPaths;           /* 0x04 */
-    U8                              PhysDiskNum;                /* 0x05 */
-    U16                             Reserved1;                  /* 0x06 */
-    U32                             Reserved2;                  /* 0x08 */
-    MPI2_RAIDPHYSDISK1_PATH         PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */
-} MPI2_CONFIG_PAGE_RD_PDISK_1,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
-  Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t;
-
-#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION          (0x02)
-
-
-/****************************************************************************
-*   values for fields used by several types of SAS Config Pages
-****************************************************************************/
-
-/* values for NegotiatedLinkRates fields */
-#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL             (0xF0)
-#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL            (4)
-#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL            (0x0F)
-/* link rates used for Negotiated Physical and Logical Link Rate */
-#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE        (0x00)
-#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED             (0x01)
-#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED       (0x02)
-#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE        (0x03)
-#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR            (0x04)
-#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS    (0x05)
-#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY          (0x06)
-#define MPI2_SAS_NEG_LINK_RATE_1_5                      (0x08)
-#define MPI2_SAS_NEG_LINK_RATE_3_0                      (0x09)
-#define MPI2_SAS_NEG_LINK_RATE_6_0                      (0x0A)
-
-
-/* values for AttachedPhyInfo fields */
-#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT       (0x00000040)
-#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS        (0x00000020)
-#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE           (0x00000010)
-
-#define MPI2_SAS_APHYINFO_REASON_MASK                   (0x0000000F)
-#define MPI2_SAS_APHYINFO_REASON_UNKNOWN                (0x00000000)
-#define MPI2_SAS_APHYINFO_REASON_POWER_ON               (0x00000001)
-#define MPI2_SAS_APHYINFO_REASON_HARD_RESET             (0x00000002)
-#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL        (0x00000003)
-#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC           (0x00000004)
-#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ       (0x00000005)
-#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER    (0x00000006)
-#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT          (0x00000007)
-#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED       (0x00000008)
-
-
-/* values for PhyInfo fields */
-#define MPI2_SAS_PHYINFO_PHY_VACANT                     (0x80000000)
-
-#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK       (0x18000000)
-#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION      (27)
-#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE               (0x00000000)
-#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL              (0x08000000)
-#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER              (0x10000000)
-
-#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS       (0x04000000)
-#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT        (0x02000000)
-#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS               (0x01000000)
-#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT          (0x00400000)
-#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS                   (0x00200000)
-#define MPI2_SAS_PHYINFO_ZONING_ENABLED                 (0x00100000)
-
-#define MPI2_SAS_PHYINFO_REASON_MASK                    (0x000F0000)
-#define MPI2_SAS_PHYINFO_REASON_UNKNOWN                 (0x00000000)
-#define MPI2_SAS_PHYINFO_REASON_POWER_ON                (0x00010000)
-#define MPI2_SAS_PHYINFO_REASON_HARD_RESET              (0x00020000)
-#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL         (0x00030000)
-#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC            (0x00040000)
-#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ        (0x00050000)
-#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER     (0x00060000)
-#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT           (0x00070000)
-#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED        (0x00080000)
-
-#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED         (0x00008000)
-#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE               (0x00004000)
-#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT     (0x00002000)
-#define MPI2_SAS_PHYINFO_VIRTUAL_PHY                    (0x00001000)
-
-#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME      (0x00000F00)
-#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME     (8)
-
-#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE         (0x000000F0)
-#define MPI2_SAS_PHYINFO_DIRECT_ROUTING                 (0x00000000)
-#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING            (0x00000010)
-#define MPI2_SAS_PHYINFO_TABLE_ROUTING                  (0x00000020)
-
-
-/* values for SAS ProgrammedLinkRate fields */
-#define MPI2_SAS_PRATE_MAX_RATE_MASK                    (0xF0)
-#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE        (0x00)
-#define MPI2_SAS_PRATE_MAX_RATE_1_5                     (0x80)
-#define MPI2_SAS_PRATE_MAX_RATE_3_0                     (0x90)
-#define MPI2_SAS_PRATE_MAX_RATE_6_0                     (0xA0)
-#define MPI25_SAS_PRATE_MAX_RATE_12_0                   (0xB0)
-#define MPI2_SAS_PRATE_MIN_RATE_MASK                    (0x0F)
-#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE        (0x00)
-#define MPI2_SAS_PRATE_MIN_RATE_1_5                     (0x08)
-#define MPI2_SAS_PRATE_MIN_RATE_3_0                     (0x09)
-#define MPI2_SAS_PRATE_MIN_RATE_6_0                     (0x0A)
-
-
-/* values for SAS HwLinkRate fields */
-#define MPI2_SAS_HWRATE_MAX_RATE_MASK                   (0xF0)
-#define MPI2_SAS_HWRATE_MAX_RATE_1_5                    (0x80)
-#define MPI2_SAS_HWRATE_MAX_RATE_3_0                    (0x90)
-#define MPI2_SAS_HWRATE_MAX_RATE_6_0                    (0xA0)
-#define MPI25_SAS_HWRATE_MAX_RATE_12_0                  (0xB0)
-#define MPI2_SAS_HWRATE_MIN_RATE_MASK                   (0x0F)
-#define MPI2_SAS_HWRATE_MIN_RATE_1_5                    (0x08)
-#define MPI2_SAS_HWRATE_MIN_RATE_3_0                    (0x09)
-#define MPI2_SAS_HWRATE_MIN_RATE_6_0                    (0x0A)
-
-
-
-/****************************************************************************
-*   SAS IO Unit Config Pages
-****************************************************************************/
-
-/* SAS IO Unit Page 0 */
-
-typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA
-{
-    U8          Port;                   /* 0x00 */
-    U8          PortFlags;              /* 0x01 */
-    U8          PhyFlags;               /* 0x02 */
-    U8          NegotiatedLinkRate;     /* 0x03 */
-    U32         ControllerPhyDeviceInfo;/* 0x04 */
-    U16         AttachedDevHandle;      /* 0x08 */
-    U16         ControllerDevHandle;    /* 0x0A */
-    U32         DiscoveryStatus;        /* 0x0C */
-    U32         Reserved;               /* 0x10 */
-} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
-  Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
-#define MPI2_SAS_IOUNIT0_PHY_MAX        (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
-    U32                                 Reserved1;                          /* 0x08 */
-    U8                                  NumPhys;                            /* 0x0C */
-    U8                                  Reserved2;                          /* 0x0D */
-    U16                                 Reserved3;                          /* 0x0E */
-    MPI2_SAS_IO_UNIT0_PHY_DATA          PhyData[MPI2_SAS_IOUNIT0_PHY_MAX];  /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
-  Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t;
-
-#define MPI2_SASIOUNITPAGE0_PAGEVERSION                     (0x05)
-
-/* values for SAS IO Unit Page 0 PortFlags */
-#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS     (0x08)
-#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG          (0x01)
-
-/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED             (0x10)
-#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED               (0x08)
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
-
-/* values for SAS IO Unit Page 0 DiscoveryStatus */
-#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
-#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
-#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED               (0x20000000)
-#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
-#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR             (0x08000000)
-#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
-#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
-#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN                (0x00002000)
-#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
-#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
-#define MPI2_SASIOUNIT0_DS_TABLE_LINK                       (0x00000400)
-#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK                 (0x00000200)
-#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR                    (0x00000100)
-#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED              (0x00000080)
-#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST                  (0x00000040)
-#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES                (0x00000020)
-#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT                      (0x00000010)
-#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS                   (0x00000004)
-#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE             (0x00000002)
-#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED                    (0x00000001)
-
-
-/* SAS IO Unit Page 1 */
-
-typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA
-{
-    U8          Port;                       /* 0x00 */
-    U8          PortFlags;                  /* 0x01 */
-    U8          PhyFlags;                   /* 0x02 */
-    U8          MaxMinLinkRate;             /* 0x03 */
-    U32         ControllerPhyDeviceInfo;    /* 0x04 */
-    U16         MaxTargetPortConnectTime;   /* 0x08 */
-    U16         Reserved1;                  /* 0x0A */
-} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
-  Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t;
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
-#define MPI2_SAS_IOUNIT1_PHY_MAX        (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                             /* 0x00 */
-    U16                                 ControlFlags;                       /* 0x08 */
-    U16                                 SASNarrowMaxQueueDepth;             /* 0x0A */
-    U16                                 AdditionalControlFlags;             /* 0x0C */
-    U16                                 SASWideMaxQueueDepth;               /* 0x0E */
-    U8                                  NumPhys;                            /* 0x10 */
-    U8                                  SATAMaxQDepth;                      /* 0x11 */
-    U8                                  ReportDeviceMissingDelay;           /* 0x12 */
-    U8                                  IODeviceMissingDelay;               /* 0x13 */
-    MPI2_SAS_IO_UNIT1_PHY_DATA          PhyData[MPI2_SAS_IOUNIT1_PHY_MAX];  /* 0x14 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_1,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
-  Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t;
-
-#define MPI2_SASIOUNITPAGE1_PAGEVERSION     (0x09)
-
-/* values for SAS IO Unit Page 1 ControlFlags */
-#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST                    (0x8000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX                        (0x4000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX                        (0x2000)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE                    (0x1000)
-
-#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT                    (0x0600)
-#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT                   (9)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH                    (0x0)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT                     (0x1)
-#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT                    (0x2)
-
-#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED             (0x0080)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED                 (0x0040)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED                   (0x0020)
-#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED                   (0x0010)
-#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL           (0x0008)
-#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL                 (0x0004)
-#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY                 (0x0002)
-#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION                   (0x0001)
-
-/* values for SAS IO Unit Page 1 AdditionalControlFlags */
-#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL          (0x0080)
-#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION    (0x0040)
-#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION        (0x0020)
-#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET   (0x0010)
-#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET  (0x0008)
-#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET   (0x0004)
-#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET     (0x0002)
-#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE               (0x0001)
-
-/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
-#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK                 (0x7F)
-#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16                      (0x80)
-
-/* values for SAS IO Unit Page 1 PortFlags */
-#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG                 (0x01)
-
-/* values for SAS IO Unit Page 1 PhyFlags */
-#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE                      (0x10)
-#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE                        (0x08)
-
-/* values for SAS IO Unit Page 1 MaxMinLinkRate */
-#define MPI2_SASIOUNIT1_MAX_RATE_MASK                               (0xF0)
-#define MPI2_SASIOUNIT1_MAX_RATE_1_5                                (0x80)
-#define MPI2_SASIOUNIT1_MAX_RATE_3_0                                (0x90)
-#define MPI2_SASIOUNIT1_MAX_RATE_6_0                                (0xA0)
-#define MPI2_SASIOUNIT1_MIN_RATE_MASK                               (0x0F)
-#define MPI2_SASIOUNIT1_MIN_RATE_1_5                                (0x08)
-#define MPI2_SASIOUNIT1_MIN_RATE_3_0                                (0x09)
-#define MPI2_SASIOUNIT1_MIN_RATE_6_0                                (0x0A)
-
-/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
-
-
-/* SAS IO Unit Page 4 */
-
-typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP
-{
-    U8          MaxTargetSpinup;            /* 0x00 */
-    U8          SpinupDelay;                /* 0x01 */
-       U8          SpinupFlags;                /* 0x02 */
-       U8          Reserved1;                  /* 0x03 */
-} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
-  Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t;
-
-/* defines for SAS IO Unit Page 4 SpinupFlags */
-#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG         (0x01)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
-#define MPI2_SAS_IOUNIT4_PHY_MAX        (4)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                         /* 0x00 */
-    MPI2_SAS_IOUNIT4_SPINUP_GROUP       SpinupGroupParameters[4];       /* 0x08 */
-    U32                                 Reserved1;                      /* 0x18 */
-    U32                                 Reserved2;                      /* 0x1C */
-    U32                                 Reserved3;                      /* 0x20 */
-    U8                                  BootDeviceWaitTime;             /* 0x24 */
-    U8                                  Reserved4;                      /* 0x25 */
-    U16                                 Reserved5;                      /* 0x26 */
-    U8                                  NumPhys;                        /* 0x28 */
-    U8                                  PEInitialSpinupDelay;           /* 0x29 */
-    U8                                  PEReplyDelay;                   /* 0x2A */
-    U8                                  Flags;                          /* 0x2B */
-    U8                                  PHY[MPI2_SAS_IOUNIT4_PHY_MAX];  /* 0x2C */
-} MPI2_CONFIG_PAGE_SASIOUNIT_4,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
-  Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t;
-
-#define MPI2_SASIOUNITPAGE4_PAGEVERSION     (0x02)
-
-/* defines for Flags field */
-#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE               (0x01)
-
-/* defines for PHY field */
-#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK               (0x03)
-
-
-/* SAS IO Unit Page 5 */
-
-typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS {
-    U8          ControlFlags;               /* 0x00 */
-    U8          PortWidthModGroup;          /* 0x01 */
-    U16         InactivityTimerExponent;    /* 0x02 */
-    U8          SATAPartialTimeout;         /* 0x04 */
-    U8          Reserved2;                  /* 0x05 */
-    U8          SATASlumberTimeout;         /* 0x06 */
-    U8          Reserved3;                  /* 0x07 */
-    U8          SASPartialTimeout;          /* 0x08 */
-    U8          Reserved4;                  /* 0x09 */
-    U8          SASSlumberTimeout;          /* 0x0A */
-    U8          Reserved5;                  /* 0x0B */
-} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
-  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS,
-  Mpi2SasIOUnit5PhyPmSettings_t, MPI2_POINTER pMpi2SasIOUnit5PhyPmSettings_t;
-
-/* defines for ControlFlags field */
-#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE      (0x08)
-#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE      (0x04)
-#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE     (0x02)
-#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE     (0x01)
-
-/* defines for PortWidthModeGroup field */
-#define MPI2_SASIOUNIT5_PWMG_DISABLE                    (0xFF)
-
-/* defines for InactivityTimerExponent field */
-#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER            (0x7000)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER           (12)
-#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL            (0x0700)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL           (8)
-#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER           (0x0070)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER          (4)
-#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL           (0x0007)
-#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL          (0)
-
-#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS                 (7)
-#define MPI2_SASIOUNIT5_ITE_ONE_SECOND                  (6)
-#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS        (5)
-#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS            (4)
-#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND             (3)
-#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS        (2)
-#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS            (1)
-#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND             (0)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumPhys at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT5_PHY_MAX
-#define MPI2_SAS_IOUNIT5_PHY_MAX        (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                /* 0x00 */
-    U8                                  NumPhys;       /* 0x08 */
-    U8                                  Reserved1;     /* 0x09 */
-    U16                                 Reserved2;     /* 0x0A */
-    U32                                 Reserved3;     /* 0x0C */
-    MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS   SASPhyPowerManagementSettings
-                                       [MPI2_SAS_IOUNIT5_PHY_MAX];  /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_5,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5,
-  Mpi2SasIOUnitPage5_t, MPI2_POINTER pMpi2SasIOUnitPage5_t;
-
-#define MPI2_SASIOUNITPAGE5_PAGEVERSION     (0x01)
-
-
-/* SAS IO Unit Page 6 */
-
-typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS {
-    U8          CurrentStatus;              /* 0x00 */
-    U8          CurrentModulation;          /* 0x01 */
-    U8          CurrentUtilization;         /* 0x02 */
-    U8          Reserved1;                  /* 0x03 */
-    U32         Reserved2;                  /* 0x04 */
-} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
-  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS,
-  Mpi2SasIOUnit6PortWidthModGroupStatus_t,
-  MPI2_POINTER pMpi2SasIOUnit6PortWidthModGroupStatus_t;
-
-/* defines for CurrentStatus field */
-#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE                      (0x00)
-#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED                     (0x01)
-#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG                   (0x02)
-#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN                        (0x03)
-#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY                 (0x04)
-#define MPI2_SASIOUNIT6_STATUS_INACTIVE                         (0x05)
-#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT                    (0x06)
-#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST                      (0x07)
-
-/* defines for CurrentModulation field */
-#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT                   (0x00)
-#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT                   (0x01)
-#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT                   (0x02)
-#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT                  (0x03)
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumGroups at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX
-#define MPI2_SAS_IOUNIT6_GROUP_MAX      (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U32                                 Reserved1;                  /* 0x08 */
-    U32                                 Reserved2;                  /* 0x0C */
-    U8                                  NumGroups;                  /* 0x10 */
-    U8                                  Reserved3;                  /* 0x11 */
-    U16                                 Reserved4;                  /* 0x12 */
-    MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS
-       PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /* 0x14 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_6,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6,
-  Mpi2SasIOUnitPage6_t, MPI2_POINTER pMpi2SasIOUnitPage6_t;
-
-#define MPI2_SASIOUNITPAGE6_PAGEVERSION     (0x00)
-
-
-/* SAS IO Unit Page 7 */
-
-typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS {
-    U8          Flags;                      /* 0x00 */
-    U8          Reserved1;                  /* 0x01 */
-    U16         Reserved2;                  /* 0x02 */
-    U8          Threshold75Pct;             /* 0x04 */
-    U8          Threshold50Pct;             /* 0x05 */
-    U8          Threshold25Pct;             /* 0x06 */
-    U8          Reserved3;                  /* 0x07 */
-} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
-  MPI2_POINTER PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS,
-  Mpi2SasIOUnit7PortWidthModGroupSettings_t,
-  MPI2_POINTER pMpi2SasIOUnit7PortWidthModGroupSettings_t;
-
-/* defines for Flags field */
-#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION  (0x01)
-
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumGroups at runtime.
- */
-#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX
-#define MPI2_SAS_IOUNIT7_GROUP_MAX      (1)
-#endif
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER            Header;             /* 0x00 */
-    U8                                          SamplingInterval;   /* 0x08 */
-    U8                                          WindowLength;       /* 0x09 */
-    U16                                         Reserved1;          /* 0x0A */
-    U32                                         Reserved2;          /* 0x0C */
-    U32                                         Reserved3;          /* 0x10 */
-    U8                                          NumGroups;          /* 0x14 */
-    U8                                          Reserved4;          /* 0x15 */
-    U16                                         Reserved5;          /* 0x16 */
-    MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS
-       PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX]; /* 0x18 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_7,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7,
-  Mpi2SasIOUnitPage7_t, MPI2_POINTER pMpi2SasIOUnitPage7_t;
-
-#define MPI2_SASIOUNITPAGE7_PAGEVERSION     (0x00)
-
-
-/* SAS IO Unit Page 8 */
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                        /* 0x00 */
-    U32                                 Reserved1;             /* 0x08 */
-    U32                                 PowerManagementCapabilities;/* 0x0C */
-    U32                                 Reserved2;             /* 0x10 */
-} MPI2_CONFIG_PAGE_SASIOUNIT_8,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8,
-  Mpi2SasIOUnitPage8_t, MPI2_POINTER pMpi2SasIOUnitPage8_t;
-
-#define MPI2_SASIOUNITPAGE8_PAGEVERSION     (0x00)
-
-/* defines for PowerManagementCapabilities field */
-#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD          (0x00001000)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE        (0x00000800)
-#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE        (0x00000400)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE       (0x00000200)
-#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE       (0x00000100)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD        (0x00000010)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE      (0x00000008)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE      (0x00000004)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE     (0x00000002)
-#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE     (0x00000001)
-
-
-
-/* SAS IO Unit Page 16 */
-
-typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 {
-       MPI2_CONFIG_EXTENDED_PAGE_HEADER  Header;                  /* 0x00 */
-       U64                         TimeStamp;                     /* 0x08 */
-       U32                         Reserved1;                     /* 0x10 */
-       U32                         Reserved2;                     /* 0x14 */
-       U32                         FastPathPendedRequests;        /* 0x18 */
-       U32                         FastPathUnPendedRequests;      /* 0x1C */
-       U32                         FastPathHostRequestStarts;     /* 0x20 */
-       U32                         FastPathFirmwareRequestStarts; /* 0x24 */
-       U32                         FastPathHostCompletions;       /* 0x28 */
-       U32                         FastPathFirmwareCompletions;   /* 0x2C */
-       U32                         NonFastPathRequestStarts;      /* 0x30 */
-       U32                         NonFastPathHostCompletions;    /* 0x30 */
-} MPI2_CONFIG_PAGE_SASIOUNIT16,
-MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT16,
-Mpi2SasIOUnitPage16_t, MPI2_POINTER pMpi2SasIOUnitPage16_t;
-
-#define MPI2_SASIOUNITPAGE16_PAGEVERSION    (0x00)
-
-
-/****************************************************************************
-*   SAS Expander Config Pages
-****************************************************************************/
-
-/* SAS Expander Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U8                                  PhysicalPort;               /* 0x08 */
-    U8                                  ReportGenLength;            /* 0x09 */
-    U16                                 EnclosureHandle;            /* 0x0A */
-    U64                                 SASAddress;                 /* 0x0C */
-    U32                                 DiscoveryStatus;            /* 0x14 */
-    U16                                 DevHandle;                  /* 0x18 */
-    U16                                 ParentDevHandle;            /* 0x1A */
-    U16                                 ExpanderChangeCount;        /* 0x1C */
-    U16                                 ExpanderRouteIndexes;       /* 0x1E */
-    U8                                  NumPhys;                    /* 0x20 */
-    U8                                  SASLevel;                   /* 0x21 */
-    U16                                 Flags;                      /* 0x22 */
-    U16                                 STPBusInactivityTimeLimit;  /* 0x24 */
-    U16                                 STPMaxConnectTimeLimit;     /* 0x26 */
-    U16                                 STP_SMP_NexusLossTime;      /* 0x28 */
-    U16                                 MaxNumRoutedSasAddresses;   /* 0x2A */
-    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       (0x06)
-
-/* values for SAS Expander Page 0 DiscoveryStatus field */
-#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED         (0x80000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED          (0x40000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED            (0x20000000)
-#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED          (0x10000000)
-#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR          (0x08000000)
-#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
-#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE         (0x00004000)
-#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN             (0x00002000)
-#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK     (0x00001000)
-#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE            (0x00000800)
-#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK                    (0x00000400)
-#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK              (0x00000200)
-#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR                 (0x00000100)
-#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED           (0x00000080)
-#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST               (0x00000040)
-#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES             (0x00000020)
-#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT                   (0x00000010)
-#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS                (0x00000004)
-#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE          (0x00000002)
-#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)
-#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT             (0x0200)
-#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING             (0x0100)
-#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT     (0x0080)
-#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE       (0x0010)
-#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG              (0x0004)
-#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS         (0x0002)
-#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG         (0x0001)
-
-
-/* SAS Expander Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U8                                  PhysicalPort;               /* 0x08 */
-    U8                                  Reserved1;                  /* 0x09 */
-    U16                                 Reserved2;                  /* 0x0A */
-    U8                                  NumPhys;                    /* 0x0C */
-    U8                                  Phy;                        /* 0x0D */
-    U16                                 NumTableEntriesProgrammed;  /* 0x0E */
-    U8                                  ProgrammedLinkRate;         /* 0x10 */
-    U8                                  HwLinkRate;                 /* 0x11 */
-    U16                                 AttachedDevHandle;          /* 0x12 */
-    U32                                 PhyInfo;                    /* 0x14 */
-    U32                                 AttachedDeviceInfo;         /* 0x18 */
-    U16                                 ExpanderDevHandle;          /* 0x1C */
-    U8                                  ChangeCount;                /* 0x1E */
-    U8                                  NegotiatedLinkRate;         /* 0x1F */
-    U8                                  PhyIdentifier;              /* 0x20 */
-    U8                                  AttachedPhyIdentifier;      /* 0x21 */
-    U8                                  Reserved3;                  /* 0x22 */
-    U8                                  DiscoveryInfo;              /* 0x23 */
-    U32                                 AttachedPhyInfo;            /* 0x24 */
-    U8                                  ZoneGroup;                  /* 0x28 */
-    U8                                  SelfConfigStatus;           /* 0x29 */
-    U16                                 Reserved4;                  /* 0x2A */
-} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
-  Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t;
-
-#define MPI2_SASEXPANDER1_PAGEVERSION       (0x02)
-
-/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
-
-/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
-
-/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
-
-/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-/* values for SAS Expander Page 1 DiscoveryInfo field */
-#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED    (0x04)
-#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE  (0x02)
-#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES  (0x01)
-
-/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
-
-/****************************************************************************
-*   SAS Device Config Pages
-****************************************************************************/
-
-/* SAS Device Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-    U16                                 Slot;                   /* 0x08 */
-    U16                                 EnclosureHandle;        /* 0x0A */
-    U64                                 SASAddress;             /* 0x0C */
-    U16                                 ParentDevHandle;        /* 0x14 */
-    U8                                  PhyNum;                 /* 0x16 */
-    U8                                  AccessStatus;           /* 0x17 */
-    U16                                 DevHandle;              /* 0x18 */
-    U8                                  AttachedPhyIdentifier;  /* 0x1A */
-    U8                                  ZoneGroup;              /* 0x1B */
-    U32                                 DeviceInfo;             /* 0x1C */
-    U16                                 Flags;                  /* 0x20 */
-    U8                                  PhysicalPort;           /* 0x22 */
-    U8                                  MaxPortConnections;     /* 0x23 */
-    U64                                 DeviceName;             /* 0x24 */
-    U8                                  PortGroups;             /* 0x2C */
-    U8                                  DmaGroup;               /* 0x2D */
-    U8                                  ControlGroup;           /* 0x2E */
-       U8                               EnclosureLevel;         /* 0x2F */
-       U8                               ConnectorName[4];       /* 0x30 */
-    U32                                 Reserved3;              /* 0x34 */
-} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
-  Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t;
-
-#define MPI2_SASDEVICE0_PAGEVERSION         (0x09)
-
-/* values for SAS Device Page 0 AccessStatus field */
-#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS                  (0x00)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED           (0x01)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED     (0x02)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT  (0x03)
-#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION  (0x04)
-#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE      (0x05)
-#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE  (0x06)
-#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED             (0x07)
-/* specific values for SATA Init failures */
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN                (0x10)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT   (0x11)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG                   (0x12)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION         (0x13)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER            (0x14)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN                 (0x15)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN                (0x16)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN                (0x17)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION       (0x18)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE        (0x19)
-#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX                    (0x1F)
-
-/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
-
-/* values for SAS Device Page 0 Flags field */
-#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE          (0x8000)
-#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE           (0x1000)
-#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE           (0x0800)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY     (0x0400)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE             (0x0200)
-#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE           (0x0100)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED     (0x0080)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED         (0x0040)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED           (0x0020)
-#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED           (0x0010)
-#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH         (0x0008)
-#define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID             (0x0002)
-#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT               (0x0001)
-
-
-/* SAS Device Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-    U32                                 Reserved1;              /* 0x08 */
-    U64                                 SASAddress;             /* 0x0C */
-    U32                                 Reserved2;              /* 0x14 */
-    U16                                 DevHandle;              /* 0x18 */
-    U16                                 Reserved3;              /* 0x1A */
-    U8                                  InitialRegDeviceFIS[20];/* 0x1C */
-} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
-  Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t;
-
-#define MPI2_SASDEVICE1_PAGEVERSION         (0x01)
-
-
-/****************************************************************************
-*   SAS PHY Config Pages
-****************************************************************************/
-
-/* SAS PHY Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-    U16                                 OwnerDevHandle;         /* 0x08 */
-    U16                                 Reserved1;              /* 0x0A */
-    U16                                 AttachedDevHandle;      /* 0x0C */
-    U8                                  AttachedPhyIdentifier;  /* 0x0E */
-    U8                                  Reserved2;              /* 0x0F */
-    U32                                 AttachedPhyInfo;        /* 0x10 */
-    U8                                  ProgrammedLinkRate;     /* 0x14 */
-    U8                                  HwLinkRate;             /* 0x15 */
-    U8                                  ChangeCount;            /* 0x16 */
-    U8                                  Flags;                  /* 0x17 */
-    U32                                 PhyInfo;                /* 0x18 */
-    U8                                  NegotiatedLinkRate;     /* 0x1C */
-    U8                                  Reserved3;              /* 0x1D */
-    U16                                 Reserved4;              /* 0x1E */
-} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
-  Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t;
-
-#define MPI2_SASPHY0_PAGEVERSION            (0x03)
-
-/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
-
-/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
-
-/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
-
-/* values for SAS PHY Page 0 Flags field */
-#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC             (0x01)
-
-/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
-
-
-/* SAS PHY Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U32                                 Reserved1;                  /* 0x08 */
-    U32                                 InvalidDwordCount;          /* 0x0C */
-    U32                                 RunningDisparityErrorCount; /* 0x10 */
-    U32                                 LossDwordSynchCount;        /* 0x14 */
-    U32                                 PhyResetProblemCount;       /* 0x18 */
-} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
-  Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t;
-
-#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 the value returned for 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 the value returned for 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 PHY Page 4 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U16                                 Reserved1;                  /* 0x08 */
-    U8                                  Reserved2;                  /* 0x0A */
-    U8                                  Flags;                      /* 0x0B */
-    U8                                  InitialFrame[28];           /* 0x0C */
-} MPI2_CONFIG_PAGE_SAS_PHY_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_4,
-  Mpi2SasPhyPage4_t, MPI2_POINTER pMpi2SasPhyPage4_t;
-
-#define MPI2_SASPHY4_PAGEVERSION            (0x00)
-
-/* values for the Flags field */
-#define MPI2_SASPHY4_FLAGS_FRAME_VALID        (0x02)
-#define MPI2_SASPHY4_FLAGS_SATA_FRAME         (0x01)
-
-
-
-
-/****************************************************************************
-*   SAS Port Config Pages
-****************************************************************************/
-
-/* SAS Port Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U8                                  PortNumber;                 /* 0x08 */
-    U8                                  PhysicalPort;               /* 0x09 */
-    U8                                  PortWidth;                  /* 0x0A */
-    U8                                  PhysicalPortWidth;          /* 0x0B */
-    U8                                  ZoneGroup;                  /* 0x0C */
-    U8                                  Reserved1;                  /* 0x0D */
-    U16                                 Reserved2;                  /* 0x0E */
-    U64                                 SASAddress;                 /* 0x10 */
-    U32                                 DeviceInfo;                 /* 0x18 */
-    U32                                 Reserved3;                  /* 0x1C */
-    U32                                 Reserved4;                  /* 0x20 */
-} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
-  Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t;
-
-#define MPI2_SASPORT0_PAGEVERSION           (0x00)
-
-/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
-
-
-/****************************************************************************
-*   SAS Enclosure Config Pages
-****************************************************************************/
-
-/* SAS Enclosure Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U32                                 Reserved1;                  /* 0x08 */
-    U64                                 EnclosureLogicalID;         /* 0x0C */
-    U16                                 Flags;                      /* 0x14 */
-    U16                                 EnclosureHandle;            /* 0x16 */
-    U16                                 NumSlots;                   /* 0x18 */
-    U16                                 StartSlot;                  /* 0x1A */
-       U8                               Reserved2;                  /* 0x1C */
-       U8                               EnclosureLevel;             /* 0x1D */
-    U16                                 SEPDevHandle;               /* 0x1E */
-    U32                                 Reserved3;                  /* 0x20 */
-    U32                                 Reserved4;                  /* 0x24 */
-} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
-  Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
-
-#define MPI2_SASENCLOSURE0_PAGEVERSION      (0x04)
-
-/* values for SAS Enclosure Page 0 Flags field */
-#define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID      (0x0010)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK              (0x000F)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN           (0x0000)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES           (0x0001)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO         (0x0002)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO         (0x0003)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE     (0x0004)
-#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO          (0x0005)
-
-
-/****************************************************************************
-*   Log Config Page
-****************************************************************************/
-
-/* Log Page 0 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumLogEntries at runtime.
- */
-#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
-#define MPI2_LOG_0_NUM_LOG_ENTRIES          (1)
-#endif
-
-#define MPI2_LOG_0_LOG_DATA_LENGTH          (0x1C)
-
-typedef struct _MPI2_LOG_0_ENTRY
-{
-    U64         TimeStamp;                          /* 0x00 */
-    U32         Reserved1;                          /* 0x08 */
-    U16         LogSequence;                        /* 0x0C */
-    U16         LogEntryQualifier;                  /* 0x0E */
-    U8          VP_ID;                              /* 0x10 */
-    U8          VF_ID;                              /* 0x11 */
-    U16         Reserved2;                          /* 0x12 */
-    U8          LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */
-} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY,
-  Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t;
-
-/* values for Log Page 0 LogEntry LogEntryQualifier field */
-#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED          (0x0000)
-#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET        (0x0001)
-#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE      (0x0002)
-#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC    (0x8000)
-#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC    (0xFFFF)
-
-typedef struct _MPI2_CONFIG_PAGE_LOG_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U32                                 Reserved1;                  /* 0x08 */
-    U32                                 Reserved2;                  /* 0x0C */
-    U16                                 NumLogEntries;              /* 0x10 */
-    U16                                 Reserved3;                  /* 0x12 */
-    MPI2_LOG_0_ENTRY                    LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */
-} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0,
-  Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t;
-
-#define MPI2_LOG_0_PAGEVERSION              (0x02)
-
-
-/****************************************************************************
-*   RAID Config Page
-****************************************************************************/
-
-/* RAID Page 0 */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check the value returned for NumElements at runtime.
- */
-#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
-#define MPI2_RAIDCONFIG0_MAX_ELEMENTS       (1)
-#endif
-
-typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT
-{
-    U16                     ElementFlags;               /* 0x00 */
-    U16                     VolDevHandle;               /* 0x02 */
-    U8                      HotSparePool;               /* 0x04 */
-    U8                      PhysDiskNum;                /* 0x05 */
-    U16                     PhysDiskDevHandle;          /* 0x06 */
-} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
-  MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
-  Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t;
-
-/* values for the ElementFlags field */
-#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE       (0x000F)
-#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT          (0x0000)
-#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT   (0x0001)
-#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT       (0x0002)
-#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT             (0x0003)
-
-
-typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    U8                                  NumHotSpares;               /* 0x08 */
-    U8                                  NumPhysDisks;               /* 0x09 */
-    U8                                  NumVolumes;                 /* 0x0A */
-    U8                                  ConfigNum;                  /* 0x0B */
-    U32                                 Flags;                      /* 0x0C */
-    U8                                  ConfigGUID[24];             /* 0x10 */
-    U32                                 Reserved1;                  /* 0x28 */
-    U8                                  NumElements;                /* 0x2C */
-    U8                                  Reserved2;                  /* 0x2D */
-    U16                                 Reserved3;                  /* 0x2E */
-    MPI2_RAIDCONFIG0_CONFIG_ELEMENT     ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */
-} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
-  Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t;
-
-#define MPI2_RAIDCONFIG0_PAGEVERSION            (0x00)
-
-/* values for RAID Configuration Page 0 Flags field */
-#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG        (0x00000001)
-
-
-/****************************************************************************
-*   Driver Persistent Mapping Config Pages
-****************************************************************************/
-
-/* Driver Persistent Mapping Page 0 */
-
-typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY
-{
-    U64                                 PhysicalIdentifier;         /* 0x00 */
-    U16                                 MappingInformation;         /* 0x08 */
-    U16                                 DeviceIndex;                /* 0x0A */
-    U32                                 PhysicalBitsMapping;        /* 0x0C */
-    U32                                 Reserved1;                  /* 0x10 */
-} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
-  Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t;
-
-typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0
-{
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                     /* 0x00 */
-    MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY  Entry;                      /* 0x08 */
-} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
-  Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t;
-
-#define MPI2_DRIVERMAPPING0_PAGEVERSION         (0x00)
-
-/* values for Driver Persistent Mapping Page 0 MappingInformation field */
-#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK              (0x07F0)
-#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT             (4)
-#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK           (0x000F)
-
-
-/****************************************************************************
-*   Ethernet Config Pages
-****************************************************************************/
-
-/* Ethernet Page 0 */
-
-/* IP address (union of IPv4 and IPv6) */
-typedef union _MPI2_ETHERNET_IP_ADDR {
-    U32     IPv4Addr;
-    U32     IPv6Addr[4];
-} MPI2_ETHERNET_IP_ADDR, MPI2_POINTER PTR_MPI2_ETHERNET_IP_ADDR,
-  Mpi2EthernetIpAddr_t, MPI2_POINTER pMpi2EthernetIpAddr_t;
-
-#define MPI2_ETHERNET_HOST_NAME_LENGTH          (32)
-
-typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-    U8                                  NumInterfaces;          /* 0x08 */
-    U8                                  Reserved0;              /* 0x09 */
-    U16                                 Reserved1;              /* 0x0A */
-    U32                                 Status;                 /* 0x0C */
-    U8                                  MediaState;             /* 0x10 */
-    U8                                  Reserved2;              /* 0x11 */
-    U16                                 Reserved3;              /* 0x12 */
-    U8                                  MacAddress[6];          /* 0x14 */
-    U8                                  Reserved4;              /* 0x1A */
-    U8                                  Reserved5;              /* 0x1B */
-    MPI2_ETHERNET_IP_ADDR               IpAddress;              /* 0x1C */
-    MPI2_ETHERNET_IP_ADDR               SubnetMask;             /* 0x2C */
-    MPI2_ETHERNET_IP_ADDR               GatewayIpAddress;       /* 0x3C */
-    MPI2_ETHERNET_IP_ADDR               DNS1IpAddress;          /* 0x4C */
-    MPI2_ETHERNET_IP_ADDR               DNS2IpAddress;          /* 0x5C */
-    MPI2_ETHERNET_IP_ADDR               DhcpIpAddress;          /* 0x6C */
-    U8                                  HostName
-                               [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
-} MPI2_CONFIG_PAGE_ETHERNET_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_0,
-  Mpi2EthernetPage0_t, MPI2_POINTER pMpi2EthernetPage0_t;
-
-#define MPI2_ETHERNETPAGE0_PAGEVERSION   (0x00)
-
-/* values for Ethernet Page 0 Status field */
-#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE             (0x80000000)
-#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE             (0x40000000)
-#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED        (0x20000000)
-#define MPI2_ETHPG0_STATUS_DEFAULT_IF               (0x00000100)
-#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED         (0x00000080)
-#define MPI2_ETHPG0_STATUS_TELNET_ENABLED           (0x00000040)
-#define MPI2_ETHPG0_STATUS_SSH2_ENABLED             (0x00000020)
-#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED      (0x00000010)
-#define MPI2_ETHPG0_STATUS_IPV6_ENABLED             (0x00000008)
-#define MPI2_ETHPG0_STATUS_IPV4_ENABLED             (0x00000004)
-#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES           (0x00000002)
-#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED           (0x00000001)
-
-/* values for Ethernet Page 0 MediaState field */
-#define MPI2_ETHPG0_MS_DUPLEX_MASK                  (0x80)
-#define MPI2_ETHPG0_MS_HALF_DUPLEX                  (0x00)
-#define MPI2_ETHPG0_MS_FULL_DUPLEX                  (0x80)
-
-#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK           (0x07)
-#define MPI2_ETHPG0_MS_NOT_CONNECTED                (0x00)
-#define MPI2_ETHPG0_MS_10MBIT                       (0x01)
-#define MPI2_ETHPG0_MS_100MBIT                      (0x02)
-#define MPI2_ETHPG0_MS_1GBIT                        (0x03)
-
-
-/* Ethernet Page 1 */
-
-typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 {
-    MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-    U32                                 Reserved0;              /* 0x08 */
-    U32                                 Flags;                  /* 0x0C */
-    U8                                  MediaState;             /* 0x10 */
-    U8                                  Reserved1;              /* 0x11 */
-    U16                                 Reserved2;              /* 0x12 */
-    U8                                  MacAddress[6];          /* 0x14 */
-    U8                                  Reserved3;              /* 0x1A */
-    U8                                  Reserved4;              /* 0x1B */
-    MPI2_ETHERNET_IP_ADDR               StaticIpAddress;        /* 0x1C */
-    MPI2_ETHERNET_IP_ADDR               StaticSubnetMask;       /* 0x2C */
-    MPI2_ETHERNET_IP_ADDR               StaticGatewayIpAddress; /* 0x3C */
-    MPI2_ETHERNET_IP_ADDR               StaticDNS1IpAddress;    /* 0x4C */
-    MPI2_ETHERNET_IP_ADDR               StaticDNS2IpAddress;    /* 0x5C */
-    U32                                 Reserved5;              /* 0x6C */
-    U32                                 Reserved6;              /* 0x70 */
-    U32                                 Reserved7;              /* 0x74 */
-    U32                                 Reserved8;              /* 0x78 */
-    U8                                  HostName
-                               [MPI2_ETHERNET_HOST_NAME_LENGTH];/* 0x7C */
-} MPI2_CONFIG_PAGE_ETHERNET_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_ETHERNET_1,
-  Mpi2EthernetPage1_t, MPI2_POINTER pMpi2EthernetPage1_t;
-
-#define MPI2_ETHERNETPAGE1_PAGEVERSION   (0x00)
-
-/* values for Ethernet Page 1 Flags field */
-#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF             (0x00000100)
-#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD         (0x00000080)
-#define MPI2_ETHPG1_FLAG_ENABLE_TELNET              (0x00000040)
-#define MPI2_ETHPG1_FLAG_ENABLE_SSH2                (0x00000020)
-#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT         (0x00000010)
-#define MPI2_ETHPG1_FLAG_ENABLE_IPV6                (0x00000008)
-#define MPI2_ETHPG1_FLAG_ENABLE_IPV4                (0x00000004)
-#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES         (0x00000002)
-#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF              (0x00000001)
-
-/* values for Ethernet Page 1 MediaState field */
-#define MPI2_ETHPG1_MS_DUPLEX_MASK                  (0x80)
-#define MPI2_ETHPG1_MS_HALF_DUPLEX                  (0x00)
-#define MPI2_ETHPG1_MS_FULL_DUPLEX                  (0x80)
-
-#define MPI2_ETHPG1_MS_DATA_RATE_MASK               (0x07)
-#define MPI2_ETHPG1_MS_DATA_RATE_AUTO               (0x00)
-#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT             (0x01)
-#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT            (0x02)
-#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT              (0x03)
-
-
-/****************************************************************************
-*   Extended Manufacturing Config Pages
-****************************************************************************/
-
-/*
- * Generic structure to use for product-specific extended manufacturing pages
- * (currently Extended Manufacturing Page 40 through Extended Manufacturing
- * Page 60).
- */
-
-typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS {
-       MPI2_CONFIG_EXTENDED_PAGE_HEADER    Header;                 /* 0x00 */
-       U32                                 ProductSpecificInfo;    /* 0x08 */
-}      MPI2_CONFIG_PAGE_EXT_MAN_PS,
-       MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS,
-       Mpi2ExtManufacturingPagePS_t,
-       MPI2_POINTER pMpi2ExtManufacturingPagePS_t;
-
-/* PageVersion should be provided by product-specific code */
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
deleted file mode 100644 (file)
index eea1a16..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 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.15
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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 because 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.
- *  10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
- *                      both SCSI IO Error Reply and SCSI Task Management Reply.
- *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
- *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
- *  02-10-10  02.00.09  Removed unused structure that had "#if 0" around it.
- *  05-12-10  02.00.10  Added optional vendor-unique region to SCSI IO Request.
- *  11-10-10  02.00.11  Added MPI2_SCSIIO_NUM_SGLOFFSETS define.
- *  02-06-12  02.00.13  Added alternate defines for Task Priority / Command
- *                      Priority to match SAM-4.
- *  07-10-12  02.00.14  Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
- *  04-09-13  02.00.15  Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY,
- *                     replacing the Reserved4 field.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_INIT_H
-#define MPI2_INIT_H
-
-/*****************************************************************************
-*
-*               SCSI Initiator Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  SCSI IO messages and associated structures
-****************************************************************************/
-
-typedef struct
-{
-    U8                      CDB[20];                    /* 0x00 */
-    U32                     PrimaryReferenceTag;        /* 0x14 */
-    U16                     PrimaryApplicationTag;      /* 0x18 */
-    U16                     PrimaryApplicationTagMask;  /* 0x1A */
-    U32                     TransferLength;             /* 0x1C */
-} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
-  Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
-
-typedef union
-{
-    U8                      CDB32[32];
-    MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
-    MPI2_SGE_SIMPLE_UNION   SGE;
-} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
-  Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
-
-/* SCSI IO Request Message */
-typedef struct _MPI2_SCSI_IO_REQUEST
-{
-    U16                     DevHandle;                      /* 0x00 */
-    U8                      ChainOffset;                    /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     Reserved1;                      /* 0x04 */
-    U8                      Reserved2;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved3;                      /* 0x0A */
-    U32                     SenseBufferLowAddress;          /* 0x0C */
-    U16                     SGLFlags;                       /* 0x10 */
-    U8                      SenseBufferLength;              /* 0x12 */
-    U8                      Reserved4;                      /* 0x13 */
-    U8                      SGLOffset0;                     /* 0x14 */
-    U8                      SGLOffset1;                     /* 0x15 */
-    U8                      SGLOffset2;                     /* 0x16 */
-    U8                      SGLOffset3;                     /* 0x17 */
-    U32                     SkipCount;                      /* 0x18 */
-    U32                     DataLength;                     /* 0x1C */
-    U32                     BidirectionalDataLength;        /* 0x20 */
-    U16                     IoFlags;                        /* 0x24 */
-    U16                     EEDPFlags;                      /* 0x26 */
-    U32                     EEDPBlockSize;                  /* 0x28 */
-    U32                     SecondaryReferenceTag;          /* 0x2C */
-    U16                     SecondaryApplicationTag;        /* 0x30 */
-    U16                     ApplicationTagTranslationMask;  /* 0x32 */
-    U8                      LUN[8];                         /* 0x34 */
-    U32                     Control;                        /* 0x3C */
-    MPI2_SCSI_IO_CDB_UNION  CDB;                            /* 0x40 */
-
-#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /* typically this is left undefined */
-       MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion;
-#endif
-
-    MPI2_SGE_IO_UNION       SGL;                            /* 0x60 */
-
-} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
-  Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
-
-/* SCSI IO MsgFlags bits */
-
-/* MsgFlags for SenseBufferAddressSpace */
-#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR        (0x0C)
-#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR      (0x00)
-#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR      (0x04)
-#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR      (0x08)
-#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR   (0x0C)
-
-/* SCSI IO SGLFlags bits */
-
-/* base values for Data Location Address Space */
-#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK              (0x0C)
-#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR            (0x00)
-#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR            (0x04)
-#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR            (0x08)
-#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR         (0x0C)
-
-/* base values for Type */
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK              (0x03)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI               (0x00)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32            (0x01)
-#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64            (0x02)
-
-/* shift values for each sub-field */
-#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT             (12)
-#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT             (8)
-#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT             (4)
-#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT             (0)
-
-/* number of SGLOffset fields */
-#define MPI2_SCSIIO_NUM_SGLOFFSETS                  (4)
-
-/* SCSI IO IoFlags bits */
-
-/* Large CDB Address Space */
-#define MPI2_SCSIIO_CDB_ADDR_MASK                   (0x6000)
-#define MPI2_SCSIIO_CDB_ADDR_SYSTEM                 (0x0000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCDDR                 (0x2000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCPLB                 (0x4000)
-#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA              (0x6000)
-
-#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB               (0x1000)
-#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL           (0x0800)
-#define MPI2_SCSIIO_IOFLAGS_MULTICAST               (0x0400)
-#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
-#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK          (0x01FF)
-
-/* SCSI IO EEDPFlags bits */
-
-#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG        (0x8000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG        (0x4000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG        (0x2000)
-#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG        (0x1000)
-
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG          (0x0400)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG          (0x0200)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD           (0x0100)
-
-#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG       (0x0008)
-
-#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP               (0x0007)
-#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP               (0x0000)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP              (0x0001)
-#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP              (0x0002)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP       (0x0003)
-#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP             (0x0004)
-#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP            (0x0006)
-#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP        (0x0007)
-
-/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
-
-/* SCSI IO Control bits */
-#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK      (0xFC000000)
-#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT     (26)
-
-#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK  (0x03000000)
-#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24)
-#define MPI2_SCSIIO_CONTROL_NODATATRANSFER      (0x00000000)
-#define MPI2_SCSIIO_CONTROL_WRITE               (0x01000000)
-#define MPI2_SCSIIO_CONTROL_READ                (0x02000000)
-#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL       (0x03000000)
-
-#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK        (0x00007800)
-#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT       (11)
-/* alternate name for the previous field; called Command Priority in SAM-4 */
-#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK         (0x00007800)
-#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT        (11)
-
-#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK  (0x00000700)
-#define MPI2_SCSIIO_CONTROL_SIMPLEQ             (0x00000000)
-#define MPI2_SCSIIO_CONTROL_HEADOFQ             (0x00000100)
-#define MPI2_SCSIIO_CONTROL_ORDEREDQ            (0x00000200)
-#define MPI2_SCSIIO_CONTROL_ACAQ                (0x00000400)
-
-#define MPI2_SCSIIO_CONTROL_TLR_MASK            (0x000000C0)
-#define MPI2_SCSIIO_CONTROL_NO_TLR              (0x00000000)
-#define MPI2_SCSIIO_CONTROL_TLR_ON              (0x00000040)
-#define MPI2_SCSIIO_CONTROL_TLR_OFF             (0x00000080)
-
-
-/* SCSI IO Error Reply Message */
-typedef struct _MPI2_SCSI_IO_REPLY
-{
-    U16                     DevHandle;                      /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     Reserved1;                      /* 0x04 */
-    U8                      Reserved2;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved3;                      /* 0x0A */
-    U8                      SCSIStatus;                     /* 0x0C */
-    U8                      SCSIState;                      /* 0x0D */
-    U16                     IOCStatus;                      /* 0x0E */
-    U32                     IOCLogInfo;                     /* 0x10 */
-    U32                     TransferCount;                  /* 0x14 */
-    U32                     SenseCount;                     /* 0x18 */
-    U32                     ResponseInfo;                   /* 0x1C */
-    U16                     TaskTag;                        /* 0x20 */
-       U16                     SCSIStatusQualifier;         /* 0x22 */
-    U32                     BidirectionalTransferCount;     /* 0x24 */
-    U32                     Reserved5;                      /* 0x28 */
-    U32                     Reserved6;                      /* 0x2C */
-} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY,
-  Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t;
-
-/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
-
-#define MPI2_SCSI_STATUS_GOOD                   (0x00)
-#define MPI2_SCSI_STATUS_CHECK_CONDITION        (0x02)
-#define MPI2_SCSI_STATUS_CONDITION_MET          (0x04)
-#define MPI2_SCSI_STATUS_BUSY                   (0x08)
-#define MPI2_SCSI_STATUS_INTERMEDIATE           (0x10)
-#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET   (0x14)
-#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT   (0x18)
-#define MPI2_SCSI_STATUS_COMMAND_TERMINATED     (0x22) /* obsolete */
-#define MPI2_SCSI_STATUS_TASK_SET_FULL          (0x28)
-#define MPI2_SCSI_STATUS_ACA_ACTIVE             (0x30)
-#define MPI2_SCSI_STATUS_TASK_ABORTED           (0x40)
-
-/* SCSI IO Reply SCSIState flags */
-
-#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID     (0x10)
-#define MPI2_SCSI_STATE_TERMINATED              (0x08)
-#define MPI2_SCSI_STATE_NO_SCSI_STATUS          (0x04)
-#define MPI2_SCSI_STATE_AUTOSENSE_FAILED        (0x02)
-#define MPI2_SCSI_STATE_AUTOSENSE_VALID         (0x01)
-
-/* masks and shifts for the ResponseInfo field */
-
-#define MPI2_SCSI_RI_MASK_REASONCODE            (0x000000FF)
-#define MPI2_SCSI_RI_SHIFT_REASONCODE           (0)
-
-#define MPI2_SCSI_TASKTAG_UNKNOWN               (0xFFFF)
-
-
-/****************************************************************************
-*  SCSI Task Management messages
-****************************************************************************/
-
-/* SCSI Task Management Request Message */
-typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
-{
-    U16                     DevHandle;                      /* 0x00 */
-    U8                      ChainOffset;                    /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U8                      Reserved1;                      /* 0x04 */
-    U8                      TaskType;                       /* 0x05 */
-    U8                      Reserved2;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved3;                      /* 0x0A */
-    U8                      LUN[8];                         /* 0x0C */
-    U32                     Reserved4[7];                   /* 0x14 */
-    U16                     TaskMID;                        /* 0x30 */
-    U16                     Reserved5;                      /* 0x32 */
-} MPI2_SCSI_TASK_MANAGE_REQUEST,
-  MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
-  Mpi2SCSITaskManagementRequest_t,
-  MPI2_POINTER pMpi2SCSITaskManagementRequest_t;
-
-/* TaskType values */
-
-#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK           (0x01)
-#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET        (0x02)
-#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET         (0x03)
-#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET   (0x05)
-#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET       (0x06)
-#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_ASYNC_EVENT      (0x0A)
-
-/* obsolete TaskType name */
-#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION  \
-       (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT)
-
-/* MsgFlags bits */
-
-#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET    (0x18)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET           (0x00)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST     (0x08)
-#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET  (0x10)
-
-#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU  (0x01)
-
-
-
-/* SCSI Task Management Reply Message */
-typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY
-{
-    U16                     DevHandle;                      /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U8                      ResponseCode;                   /* 0x04 */
-    U8                      TaskType;                       /* 0x05 */
-    U8                      Reserved1;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved2;                      /* 0x0A */
-    U16                     Reserved3;                      /* 0x0C */
-    U16                     IOCStatus;                      /* 0x0E */
-    U32                     IOCLogInfo;                     /* 0x10 */
-    U32                     TerminationCount;               /* 0x14 */
-    U32                     ResponseInfo;                   /* 0x18 */
-} MPI2_SCSI_TASK_MANAGE_REPLY,
-  MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
-  Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t;
-
-/* ResponseCode values */
-
-#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE               (0x00)
-#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME             (0x02)
-#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED          (0x04)
-#define MPI2_SCSITASKMGMT_RSP_TM_FAILED                 (0x05)
-#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED              (0x08)
-#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN            (0x09)
-#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG         (0x0A)
-#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC          (0x80)
-
-/* masks and shifts for the ResponseInfo field */
-
-#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE            (0x000000FF)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE           (0)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI2                  (0x0000FF00)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2                 (8)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI1                  (0x00FF0000)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1                 (16)
-#define MPI2_SCSITASKMGMT_RI_MASK_ARI0                  (0xFF000000)
-#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0                 (24)
-
-
-/****************************************************************************
-*  SCSI Enclosure Processor messages
-****************************************************************************/
-
-/* SCSI Enclosure Processor Request Message */
-typedef struct _MPI2_SEP_REQUEST
-{
-    U16                     DevHandle;          /* 0x00 */
-    U8                      ChainOffset;        /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U8                      Action;             /* 0x04 */
-    U8                      Flags;              /* 0x05 */
-    U8                      Reserved1;          /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved2;          /* 0x0A */
-    U32                     SlotStatus;         /* 0x0C */
-    U32                     Reserved3;          /* 0x10 */
-    U32                     Reserved4;          /* 0x14 */
-    U32                     Reserved5;          /* 0x18 */
-    U16                     Slot;               /* 0x1C */
-    U16                     EnclosureHandle;    /* 0x1E */
-} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST,
-  Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t;
-
-/* Action defines */
-#define MPI2_SEP_REQ_ACTION_WRITE_STATUS                (0x00)
-#define MPI2_SEP_REQ_ACTION_READ_STATUS                 (0x01)
-
-/* Flags defines */
-#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS            (0x00)
-#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS       (0x01)
-
-/* SlotStatus defines */
-#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE          (0x00040000)
-#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST        (0x00020000)
-#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED         (0x00000200)
-#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)
-
-
-/* SCSI Enclosure Processor Reply Message */
-typedef struct _MPI2_SEP_REPLY
-{
-    U16                     DevHandle;          /* 0x00 */
-    U8                      MsgLength;          /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U8                      Action;             /* 0x04 */
-    U8                      Flags;              /* 0x05 */
-    U8                      Reserved1;          /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved2;          /* 0x0A */
-    U16                     Reserved3;          /* 0x0C */
-    U16                     IOCStatus;          /* 0x0E */
-    U32                     IOCLogInfo;         /* 0x10 */
-    U32                     SlotStatus;         /* 0x14 */
-    U32                     Reserved4;          /* 0x18 */
-    U16                     Slot;               /* 0x1C */
-    U16                     EnclosureHandle;    /* 0x1E */
-} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY,
-  Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t;
-
-/* SlotStatus defines */
-#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY          (0x00040000)
-#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST      (0x00020000)
-#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED       (0x00000200)
-#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)
-
-
-#endif
-
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
deleted file mode 100644 (file)
index b02de48..0000000
+++ /dev/null
@@ -1,1708 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_ioc.h
- *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
- *  Creation Date:  October 11, 2006
- *
- *  mpi2_ioc.h Version:  02.00.24
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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.
- *  07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
- *                      Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- *                      Added new product id family for 2208.
- *  10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
- *                      Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
- *                      Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
- *                      Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
- *                      Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
- *                      Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
- *                      Added Host Based Discovery Phy Event data.
- *                      Added defines for ProductID Product field
- *                      (MPI2_FW_HEADER_PID_).
- *                      Modified values for SAS ProductID Family
- *                      (MPI2_FW_HEADER_PID_FAMILY_).
- *  02-10-10  02.00.14  Added SAS Quiesce Event structure and defines.
- *                      Added PowerManagementControl Request structures and
- *                      defines.
- *  05-12-10  02.00.15  Marked Task Set Full Event as obsolete.
- *                      Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define.
- *  11-10-10  02.00.16  Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC.
- *  02-23-11  02.00.17  Added SAS NOTIFY Primitive event, and added
- *                      SASNotifyPrimitiveMasks field to
- *                      MPI2_EVENT_NOTIFICATION_REQUEST.
- *                      Added Temperature Threshold Event.
- *                      Added Host Message Event.
- *                      Added Send Host Message request and reply.
- *  05-25-11  02.00.18  For Extended Image Header, added
- *                      MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and
- *                      MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines.
- *                      Deprecated MPI2_EXT_IMAGE_TYPE_MAX define.
- *  08-24-11  02.00.19  Added PhysicalPort field to
- *                      MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure.
- *                      Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete.
- *  03-29-12  02.00.21  Added a product specific range to event values.
- *  07-26-12  02.00.22  Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE.
- *                      Added ElapsedSeconds field to
- *                      MPI2_EVENT_DATA_IR_OPERATION_STATUS.
- *  08-19-13  02.00.23  For IOCInit, added MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE
- *                      and MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY.
- *                      Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE.
- *                      Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY.
- *                      Added Encrypted Hash Extended Image.
- *  12-05-13  02.00.24  Added MPI25_HASH_IMAGE_TYPE_BIOS.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_IOC_H
-#define MPI2_IOC_H
-
-/*****************************************************************************
-*
-*               IOC Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  IOCInit message
-****************************************************************************/
-
-/* IOCInit Request message */
-typedef struct _MPI2_IOC_INIT_REQUEST
-{
-    U8                      WhoInit;                        /* 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 */
-    U16                     MsgVersion;                     /* 0x0C */
-    U16                     HeaderVersion;                  /* 0x0E */
-    U32                     Reserved5;                      /* 0x10 */
-    U16                     Reserved6;                      /* 0x14 */
-    U8                      Reserved7;                      /* 0x16 */
-    U8                      HostMSIxVectors;                /* 0x17 */
-    U16                     Reserved8;                      /* 0x18 */
-    U16                     SystemRequestFrameSize;         /* 0x1A */
-    U16                     ReplyDescriptorPostQueueDepth;  /* 0x1C */
-    U16                     ReplyFreeQueueDepth;            /* 0x1E */
-    U32                     SenseBufferAddressHigh;         /* 0x20 */
-    U32                     SystemReplyAddressHigh;         /* 0x24 */
-    U64                     SystemRequestFrameBaseAddress;  /* 0x28 */
-    U64                     ReplyDescriptorPostQueueAddress;/* 0x30 */
-    U64                     ReplyFreeQueueAddress;          /* 0x38 */
-    U64                     TimeStamp;                      /* 0x40 */
-} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
-  Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
-
-/* WhoInit values */
-#define MPI2_WHOINIT_NOT_INITIALIZED            (0x00)
-#define MPI2_WHOINIT_SYSTEM_BIOS                (0x01)
-#define MPI2_WHOINIT_ROM_BIOS                   (0x02)
-#define MPI2_WHOINIT_PCI_PEER                   (0x03)
-#define MPI2_WHOINIT_HOST_DRIVER                (0x04)
-#define MPI2_WHOINIT_MANUFACTURER               (0x05)
-
-/* MsgFlags */
-#define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE    (0x01)
-
-/* MsgVersion */
-#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK      (0xFF00)
-#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT     (8)
-#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK      (0x00FF)
-#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT     (0)
-
-/* HeaderVersion */
-#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK       (0xFF00)
-#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT      (8)
-#define MPI2_IOCINIT_HDRVERSION_DEV_MASK        (0x00FF)
-#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT       (0)
-
-/* minimum depth for a Reply Descriptor Post Queue */
-#define MPI2_RDPQ_DEPTH_MIN                     (16)
-
-/* Reply Descriptor Post Queue Array Entry */
-typedef struct _MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
-       U64                 RDPQBaseAddress;                    /* 0x00 */
-       U32                 Reserved1;                          /* 0x08 */
-       U32                 Reserved2;                          /* 0x0C */
-} MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY,
-MPI2_POINTER PTR_MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY,
-Mpi2IOCInitRDPQArrayEntry, MPI2_POINTER pMpi2IOCInitRDPQArrayEntry;
-
-/* IOCInit Reply message */
-typedef struct _MPI2_IOC_INIT_REPLY
-{
-    U8                      WhoInit;                        /* 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 */
-} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY,
-  Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t;
-
-
-/****************************************************************************
-*  IOCFacts message
-****************************************************************************/
-
-/* IOCFacts Request message */
-typedef struct _MPI2_IOC_FACTS_REQUEST
-{
-    U16                     Reserved1;                      /* 0x00 */
-    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 */
-} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST,
-  Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t;
-
-
-/* IOCFacts Reply message */
-typedef struct _MPI2_IOC_FACTS_REPLY
-{
-    U16                     MsgVersion;                     /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     HeaderVersion;                  /* 0x04 */
-    U8                      IOCNumber;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved1;                      /* 0x0A */
-    U16                     IOCExceptions;                  /* 0x0C */
-    U16                     IOCStatus;                      /* 0x0E */
-    U32                     IOCLogInfo;                     /* 0x10 */
-    U8                      MaxChainDepth;                  /* 0x14 */
-    U8                      WhoInit;                        /* 0x15 */
-    U8                      NumberOfPorts;                  /* 0x16 */
-    U8                      MaxMSIxVectors;                 /* 0x17 */
-    U16                     RequestCredit;                  /* 0x18 */
-    U16                     ProductID;                      /* 0x1A */
-    U32                     IOCCapabilities;                /* 0x1C */
-    MPI2_VERSION_UNION      FWVersion;                      /* 0x20 */
-    U16                     IOCRequestFrameSize;            /* 0x24 */
-    U16                     Reserved3;                      /* 0x26 */
-    U16                     MaxInitiators;                  /* 0x28 */
-    U16                     MaxTargets;                     /* 0x2A */
-    U16                     MaxSasExpanders;                /* 0x2C */
-    U16                     MaxEnclosures;                  /* 0x2E */
-    U16                     ProtocolFlags;                  /* 0x30 */
-    U16                     HighPriorityCredit;             /* 0x32 */
-    U16                     MaxReplyDescriptorPostQueueDepth; /* 0x34 */
-    U8                      ReplyFrameSize;                 /* 0x36 */
-    U8                      MaxVolumes;                     /* 0x37 */
-    U16                     MaxDevHandle;                   /* 0x38 */
-    U16                     MaxPersistentEntries;           /* 0x3A */
-    U16                     MinDevHandle;                   /* 0x3C */
-    U16                     Reserved4;                      /* 0x3E */
-} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY,
-  Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t;
-
-/* MsgVersion */
-#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK             (0xFF00)
-#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT            (8)
-#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK             (0x00FF)
-#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT            (0)
-
-/* HeaderVersion */
-#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK              (0xFF00)
-#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT             (8)
-#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK               (0x00FF)
-#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT              (0)
-
-/* IOCExceptions */
-#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE     (0x0200)
-#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX      (0x0100)
-
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK              (0x00E0)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD              (0x0000)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP            (0x0020)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED          (0x0040)
-#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP    (0x0060)
-
-#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED       (0x0010)
-#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL     (0x0008)
-#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL           (0x0004)
-#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID        (0x0002)
-#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL       (0x0001)
-
-/* defines for WhoInit field are after the IOCInit Request */
-
-/* ProductID field uses MPI2_FW_HEADER_PID_ */
-
-/* IOCCapabilities */
-#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE     (0x00040000)
-#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY   (0x00010000)
-#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)
-#define MPI2_IOCFACTS_CAPABILITY_MULTICAST              (0x00000100)
-#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET   (0x00000080)
-#define MPI2_IOCFACTS_CAPABILITY_EEDP                   (0x00000040)
-#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER        (0x00000020)
-#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER        (0x00000010)
-#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER      (0x00000008)
-#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
-
-/* ProtocolFlags */
-#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET              (0x0001)
-#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR           (0x0002)
-
-
-/****************************************************************************
-*  PortFacts message
-****************************************************************************/
-
-/* PortFacts Request message */
-typedef struct _MPI2_PORT_FACTS_REQUEST
-{
-    U16                     Reserved1;                      /* 0x00 */
-    U8                      ChainOffset;                    /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     Reserved2;                      /* 0x04 */
-    U8                      PortNumber;                     /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved3;                      /* 0x0A */
-} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST,
-  Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t;
-
-/* PortFacts Reply message */
-typedef struct _MPI2_PORT_FACTS_REPLY
-{
-    U16                     Reserved1;                      /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     Reserved2;                      /* 0x04 */
-    U8                      PortNumber;                     /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved3;                      /* 0x0A */
-    U16                     Reserved4;                      /* 0x0C */
-    U16                     IOCStatus;                      /* 0x0E */
-    U32                     IOCLogInfo;                     /* 0x10 */
-    U8                      Reserved5;                      /* 0x14 */
-    U8                      PortType;                       /* 0x15 */
-    U16                     Reserved6;                      /* 0x16 */
-    U16                     MaxPostedCmdBuffers;            /* 0x18 */
-    U16                     Reserved7;                      /* 0x1A */
-} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY,
-  Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t;
-
-/* PortType values */
-#define MPI2_PORTFACTS_PORTTYPE_INACTIVE            (0x00)
-#define MPI2_PORTFACTS_PORTTYPE_FC                  (0x10)
-#define MPI2_PORTFACTS_PORTTYPE_ISCSI               (0x20)
-#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL        (0x30)
-#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL         (0x31)
-
-
-/****************************************************************************
-*  PortEnable message
-****************************************************************************/
-
-/* PortEnable Request message */
-typedef struct _MPI2_PORT_ENABLE_REQUEST
-{
-    U16                     Reserved1;                      /* 0x00 */
-    U8                      ChainOffset;                    /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U8                      Reserved2;                      /* 0x04 */
-    U8                      PortFlags;                      /* 0x05 */
-    U8                      Reserved3;                      /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved4;                      /* 0x0A */
-} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST,
-  Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t;
-
-
-/* PortEnable Reply message */
-typedef struct _MPI2_PORT_ENABLE_REPLY
-{
-    U16                     Reserved1;                      /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U8                      Reserved2;                      /* 0x04 */
-    U8                      PortFlags;                      /* 0x05 */
-    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 */
-} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY,
-  Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t;
-
-
-/****************************************************************************
-*  EventNotification message
-****************************************************************************/
-
-/* EventNotification Request message */
-#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS           (4)
-
-typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
-{
-    U16                     Reserved1;                      /* 0x00 */
-    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 */
-    U32                     EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
-    U16                     SASBroadcastPrimitiveMasks;     /* 0x24 */
-        U16                     SASNotifyPrimitiveMasks;        /* 0x26 */
-    U32                     Reserved8;                      /* 0x28 */
-} MPI2_EVENT_NOTIFICATION_REQUEST,
-  MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
-  Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t;
-
-
-/* EventNotification Reply message */
-typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
-{
-    U16                     EventDataLength;                /* 0x00 */
-    U8                      MsgLength;                      /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     Reserved1;                      /* 0x04 */
-    U8                      AckRequired;                    /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved2;                      /* 0x0A */
-    U16                     Reserved3;                      /* 0x0C */
-    U16                     IOCStatus;                      /* 0x0E */
-    U32                     IOCLogInfo;                     /* 0x10 */
-    U16                     Event;                          /* 0x14 */
-    U16                     Reserved4;                      /* 0x16 */
-    U32                     EventContext;                   /* 0x18 */
-    U32                     EventData[1];                   /* 0x1C */
-} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY,
-  Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t;
-
-/* AckRequired */
-#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED    (0x00)
-#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED        (0x01)
-
-/* Event */
-#define MPI2_EVENT_LOG_DATA                         (0x0001)
-#define MPI2_EVENT_STATE_CHANGE                     (0x0002)
-#define MPI2_EVENT_HARD_RESET_RECEIVED              (0x0005)
-#define MPI2_EVENT_EVENT_CHANGE                     (0x000A)
-#define MPI2_EVENT_TASK_SET_FULL                    (0x000E) /* obsolete */
-#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE         (0x000F)
-#define MPI2_EVENT_IR_OPERATION_STATUS              (0x0014)
-#define MPI2_EVENT_SAS_DISCOVERY                    (0x0016)
-#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE          (0x0017)
-#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE    (0x0018)
-#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW          (0x0019)
-#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST         (0x001C)
-#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE    (0x001D)
-#define MPI2_EVENT_IR_VOLUME                        (0x001E)
-#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)
-#define MPI2_EVENT_GPIO_INTERRUPT                   (0x0023)
-#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY         (0x0024)
-#define MPI2_EVENT_SAS_QUIESCE                      (0x0025)
-#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE             (0x0026)
-#define MPI2_EVENT_TEMP_THRESHOLD                   (0x0027)
-#define MPI2_EVENT_HOST_MESSAGE                     (0x0028)
-#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC             (0x006E)
-#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC             (0x007F)
-
-/* Log Entry Added Event data */
-
-/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
-#define MPI2_EVENT_DATA_LOG_DATA_LENGTH             (0x1C)
-
-typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED
-{
-    U64         TimeStamp;                          /* 0x00 */
-    U32         Reserved1;                          /* 0x08 */
-    U16         LogSequence;                        /* 0x0C */
-    U16         LogEntryQualifier;                  /* 0x0E */
-    U8          VP_ID;                              /* 0x10 */
-    U8          VF_ID;                              /* 0x11 */
-    U16         Reserved2;                          /* 0x12 */
-    U8          LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */
-} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
-  Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t;
-
-/* GPIO Interrupt Event data */
-
-typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT {
-    U8          GPIONum;                            /* 0x00 */
-    U8          Reserved1;                          /* 0x01 */
-    U16         Reserved2;                          /* 0x02 */
-} MPI2_EVENT_DATA_GPIO_INTERRUPT,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT,
-  Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t;
-
-/* Temperature Threshold Event data */
-
-typedef struct _MPI2_EVENT_DATA_TEMPERATURE {
-       U16         Status;                             /* 0x00 */
-       U8          SensorNum;                          /* 0x02 */
-       U8          Reserved1;                          /* 0x03 */
-       U16         CurrentTemperature;                 /* 0x04 */
-       U16         Reserved2;                          /* 0x06 */
-       U32         Reserved3;                          /* 0x08 */
-       U32         Reserved4;                          /* 0x0C */
-} MPI2_EVENT_DATA_TEMPERATURE,
-MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE,
-Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t;
-
-/* Temperature Threshold Event data Status bits */
-#define MPI2_EVENT_TEMPERATURE3_EXCEEDED            (0x0008)
-#define MPI2_EVENT_TEMPERATURE2_EXCEEDED            (0x0004)
-#define MPI2_EVENT_TEMPERATURE1_EXCEEDED            (0x0002)
-#define MPI2_EVENT_TEMPERATURE0_EXCEEDED            (0x0001)
-
-
-/* Host Message Event data */
-
-typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE {
-       U8          SourceVF_ID;                        /* 0x00 */
-       U8          Reserved1;                          /* 0x01 */
-       U16         Reserved2;                          /* 0x02 */
-       U32         Reserved3;                          /* 0x04 */
-       U32         HostData[1];                        /* 0x08 */
-} MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE,
-Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t;
-
-
-/* Hard Reset Received Event data */
-
-typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
-{
-    U8                      Reserved1;                      /* 0x00 */
-    U8                      Port;                           /* 0x01 */
-    U16                     Reserved2;                      /* 0x02 */
-} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
-  Mpi2EventDataHardResetReceived_t,
-  MPI2_POINTER pMpi2EventDataHardResetReceived_t;
-
-/* Task Set Full Event data */
-/*   this event is obsolete */
-
-typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
-{
-    U16                     DevHandle;                      /* 0x00 */
-    U16                     CurrentDepth;                   /* 0x02 */
-} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
-  Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t;
-
-
-/* SAS Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
-{
-    U16                     TaskTag;                        /* 0x00 */
-    U8                      ReasonCode;                     /* 0x02 */
-       U8                      PhysicalPort;                   /* 0x03 */
-    U8                      ASC;                            /* 0x04 */
-    U8                      ASCQ;                           /* 0x05 */
-    U16                     DevHandle;                      /* 0x06 */
-    U32                     Reserved2;                      /* 0x08 */
-    U64                     SASAddress;                     /* 0x0C */
-    U8                      LUN[8];                         /* 0x14 */
-} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
-  Mpi2EventDataSasDeviceStatusChange_t,
-  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_EXPANDER_REDUCED_FUNCTIONALITY       (0x11)
-#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY   (0x12)
-
-
-/* Integrated RAID Operation Status Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
-{
-    U16                     VolDevHandle;               /* 0x00 */
-    U16                     Reserved1;                  /* 0x02 */
-    U8                      RAIDOperation;              /* 0x04 */
-    U8                      PercentComplete;            /* 0x05 */
-    U16                     Reserved2;                  /* 0x06 */
-       U32                     ElapsedSeconds;             /* 0x08 */
-} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
-  Mpi2EventDataIrOperationStatus_t,
-  MPI2_POINTER pMpi2EventDataIrOperationStatus_t;
-
-/* Integrated RAID Operation Status Event data RAIDOperation values */
-#define MPI2_EVENT_IR_RAIDOP_RESYNC                     (0x00)
-#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION       (0x01)
-#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK          (0x02)
-#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT            (0x03)
-#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT       (0x04)
-
-
-/* Integrated RAID Volume Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_VOLUME
-{
-    U16                     VolDevHandle;               /* 0x00 */
-    U8                      ReasonCode;                 /* 0x02 */
-    U8                      Reserved1;                  /* 0x03 */
-    U32                     NewValue;                   /* 0x04 */
-    U32                     PreviousValue;              /* 0x08 */
-} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME,
-  Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t;
-
-/* Integrated RAID Volume Event data ReasonCode values */
-#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED        (0x01)
-#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED    (0x02)
-#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED           (0x03)
-
-
-/* Integrated RAID Physical Disk Event data */
-
-typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK
-{
-    U16                     Reserved1;                  /* 0x00 */
-    U8                      ReasonCode;                 /* 0x02 */
-    U8                      PhysDiskNum;                /* 0x03 */
-    U16                     PhysDiskDevHandle;          /* 0x04 */
-    U16                     Reserved2;                  /* 0x06 */
-    U16                     Slot;                       /* 0x08 */
-    U16                     EnclosureHandle;            /* 0x0A */
-    U32                     NewValue;                   /* 0x0C */
-    U32                     PreviousValue;              /* 0x10 */
-} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
-  Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t;
-
-/* Integrated RAID Physical Disk Event data ReasonCode values */
-#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED      (0x01)
-#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED  (0x02)
-#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED         (0x03)
-
-
-/* Integrated RAID Configuration Change List Event data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumElements at runtime.
- */
-#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
-#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT          (1)
-#endif
-
-typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT
-{
-    U16                     ElementFlags;               /* 0x00 */
-    U16                     VolDevHandle;               /* 0x02 */
-    U8                      ReasonCode;                 /* 0x04 */
-    U8                      PhysDiskNum;                /* 0x05 */
-    U16                     PhysDiskDevHandle;          /* 0x06 */
-} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
-  Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t;
-
-/* IR Configuration Change List Event data ElementFlags values */
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK   (0x000F)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT      (0x0000)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
-#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT    (0x0002)
-
-/* IR Configuration Change List Event data ReasonCode values */
-#define MPI2_EVENT_IR_CHANGE_RC_ADDED                   (0x01)
-#define MPI2_EVENT_IR_CHANGE_RC_REMOVED                 (0x02)
-#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE               (0x03)
-#define MPI2_EVENT_IR_CHANGE_RC_HIDE                    (0x04)
-#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE                  (0x05)
-#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED          (0x06)
-#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED          (0x07)
-#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED              (0x08)
-#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED              (0x09)
-
-typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST
-{
-    U8                              NumElements;        /* 0x00 */
-    U8                              Reserved1;          /* 0x01 */
-    U8                              Reserved2;          /* 0x02 */
-    U8                              ConfigNum;          /* 0x03 */
-    U32                             Flags;              /* 0x04 */
-    MPI2_EVENT_IR_CONFIG_ELEMENT    ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];    /* 0x08 */
-} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
-  Mpi2EventDataIrConfigChangeList_t,
-  MPI2_POINTER pMpi2EventDataIrConfigChangeList_t;
-
-/* IR Configuration Change List Event data Flags values */
-#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG   (0x00000001)
-
-
-/* SAS Discovery Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY
-{
-    U8                      Flags;                      /* 0x00 */
-    U8                      ReasonCode;                 /* 0x01 */
-    U8                      PhysicalPort;               /* 0x02 */
-    U8                      Reserved1;                  /* 0x03 */
-    U32                     DiscoveryStatus;            /* 0x04 */
-} MPI2_EVENT_DATA_SAS_DISCOVERY,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
-  Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t;
-
-/* SAS Discovery Event data Flags values */
-#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE                   (0x02)
-#define MPI2_EVENT_SAS_DISC_IN_PROGRESS                     (0x01)
-
-/* SAS Discovery Event data ReasonCode values */
-#define MPI2_EVENT_SAS_DISC_RC_STARTED                      (0x01)
-#define MPI2_EVENT_SAS_DISC_RC_COMPLETED                    (0x02)
-
-/* SAS Discovery Event data DiscoveryStatus values */
-#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED            (0x80000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED             (0x40000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED               (0x20000000)
-#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED             (0x10000000)
-#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR             (0x08000000)
-#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE    (0x00008000)
-#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE            (0x00004000)
-#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN                (0x00002000)
-#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK        (0x00001000)
-#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE               (0x00000800)
-#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK                       (0x00000400)
-#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK                 (0x00000200)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR                    (0x00000100)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED              (0x00000080)
-#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST                  (0x00000040)
-#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES                (0x00000020)
-#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT                      (0x00000010)
-#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS                   (0x00000004)
-#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE             (0x00000002)
-#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED                    (0x00000001)
-
-
-/* SAS Broadcast Primitive Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
-{
-    U8                      PhyNum;                     /* 0x00 */
-    U8                      Port;                       /* 0x01 */
-    U8                      PortWidth;                  /* 0x02 */
-    U8                      Primitive;                  /* 0x03 */
-} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
-  Mpi2EventDataSasBroadcastPrimitive_t,
-  MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t;
-
-/* defines for the Primitive field */
-#define MPI2_EVENT_PRIMITIVE_CHANGE                         (0x01)
-#define MPI2_EVENT_PRIMITIVE_SES                            (0x02)
-#define MPI2_EVENT_PRIMITIVE_EXPANDER                       (0x03)
-#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT             (0x04)
-#define MPI2_EVENT_PRIMITIVE_RESERVED3                      (0x05)
-#define MPI2_EVENT_PRIMITIVE_RESERVED4                      (0x06)
-#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED               (0x07)
-#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED               (0x08)
-
-/* SAS Notify Primitive Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE {
-       U8                      PhyNum;                     /* 0x00 */
-       U8                      Port;                       /* 0x01 */
-       U8                      Reserved1;                  /* 0x02 */
-       U8                      Primitive;                  /* 0x03 */
-} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
-MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE,
-Mpi2EventDataSasNotifyPrimitive_t,
-MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t;
-
-/* defines for the Primitive field */
-#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP                     (0x01)
-#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED               (0x02)
-#define MPI2_EVENT_NOTIFY_RESERVED1                         (0x03)
-#define MPI2_EVENT_NOTIFY_RESERVED2                         (0x04)
-
-
-/* SAS Initiator Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
-{
-    U8                      ReasonCode;                 /* 0x00 */
-    U8                      PhysicalPort;               /* 0x01 */
-    U16                     DevHandle;                  /* 0x02 */
-    U64                     SASAddress;                 /* 0x04 */
-} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
-  Mpi2EventDataSasInitDevStatusChange_t,
-  MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t;
-
-/* SAS Initiator Device Status Change event ReasonCode values */
-#define MPI2_EVENT_SAS_INIT_RC_ADDED                (0x01)
-#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING       (0x02)
-
-
-/* SAS Initiator Device Table Overflow Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
-{
-    U16                     MaxInit;                    /* 0x00 */
-    U16                     CurrentInit;                /* 0x02 */
-    U64                     SASAddress;                 /* 0x04 */
-} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
-  Mpi2EventDataSasInitTableOverflow_t,
-  MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t;
-
-
-/* SAS Topology Change List Event data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumEntries at runtime.
- */
-#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
-#define MPI2_EVENT_SAS_TOPO_PHY_COUNT           (1)
-#endif
-
-typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY
-{
-    U16                     AttachedDevHandle;          /* 0x00 */
-    U8                      LinkRate;                   /* 0x02 */
-    U8                      PhyStatus;                  /* 0x03 */
-} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
-  Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t;
-
-typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
-{
-    U16                             EnclosureHandle;            /* 0x00 */
-    U16                             ExpanderDevHandle;          /* 0x02 */
-    U8                              NumPhys;                    /* 0x04 */
-    U8                              Reserved1;                  /* 0x05 */
-    U16                             Reserved2;                  /* 0x06 */
-    U8                              NumEntries;                 /* 0x08 */
-    U8                              StartPhyNum;                /* 0x09 */
-    U8                              ExpStatus;                  /* 0x0A */
-    U8                              PhysicalPort;               /* 0x0B */
-    MPI2_EVENT_SAS_TOPO_PHY_ENTRY   PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/
-} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
-  Mpi2EventDataSasTopologyChangeList_t,
-  MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t;
-
-/* values for the ExpStatus field */
-#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER                  (0x00)
-#define MPI2_EVENT_SAS_TOPO_ES_ADDED                        (0x01)
-#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING               (0x02)
-#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING                   (0x03)
-#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING         (0x04)
-
-/* defines for the LinkRate field */
-#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK                 (0xF0)
-#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT                (4)
-#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK                    (0x0F)
-#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT                   (0)
-
-#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE            (0x00)
-#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED                 (0x01)
-#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED           (0x02)
-#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE            (0x03)
-#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR                (0x04)
-#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS        (0x05)
-#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY              (0x06)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5                     (0x08)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0                     (0x09)
-#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0                     (0x0A)
-
-/* values for the PhyStatus field */
-#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT                (0x80)
-#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE             (0x10)
-/* values for the PhyStatus ReasonCode sub-field */
-#define MPI2_EVENT_SAS_TOPO_RC_MASK                         (0x0F)
-#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED                   (0x01)
-#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING          (0x02)
-#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED                  (0x03)
-#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE                    (0x04)
-#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING         (0x05)
-
-
-/* SAS Enclosure Device Status Change Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
-{
-    U16                     EnclosureHandle;            /* 0x00 */
-    U8                      ReasonCode;                 /* 0x02 */
-    U8                      PhysicalPort;               /* 0x03 */
-    U64                     EnclosureLogicalID;         /* 0x04 */
-    U16                     NumSlots;                   /* 0x0C */
-    U16                     StartSlot;                  /* 0x0E */
-    U32                     PhyBits;                    /* 0x10 */
-} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
-  Mpi2EventDataSasEnclDevStatusChange_t,
-  MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
-
-/* SAS Enclosure Device Status Change event ReasonCode values */
-#define MPI2_EVENT_SAS_ENCL_RC_ADDED                (0x01)
-#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
- * */
-
-
-/* SAS Quiesce Event data */
-
-typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE {
-    U8                      ReasonCode;                 /* 0x00 */
-    U8                      Reserved1;                  /* 0x01 */
-    U16                     Reserved2;                  /* 0x02 */
-    U32                     Reserved3;                  /* 0x04 */
-} MPI2_EVENT_DATA_SAS_QUIESCE,
-  MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE,
-  Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t;
-
-/* SAS Quiesce Event data ReasonCode values */
-#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED                   (0x01)
-#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED                 (0x02)
-
-
-/* Host Based Discovery Phy Event data */
-
-typedef struct _MPI2_EVENT_HBD_PHY_SAS {
-    U8          Flags;                      /* 0x00 */
-    U8          NegotiatedLinkRate;         /* 0x01 */
-    U8          PhyNum;                     /* 0x02 */
-    U8          PhysicalPort;               /* 0x03 */
-    U32         Reserved1;                  /* 0x04 */
-    U8          InitialFrame[28];           /* 0x08 */
-} MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS,
-  Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t;
-
-/* values for the Flags field */
-#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID        (0x02)
-#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME         (0x01)
-
-/* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for
- * the NegotiatedLinkRate field */
-
-typedef union _MPI2_EVENT_HBD_DESCRIPTOR {
-    MPI2_EVENT_HBD_PHY_SAS      Sas;
-} MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR,
-  Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t;
-
-typedef struct _MPI2_EVENT_DATA_HBD_PHY {
-    U8                          DescriptorType;     /* 0x00 */
-    U8                          Reserved1;          /* 0x01 */
-    U16                         Reserved2;          /* 0x02 */
-    U32                         Reserved3;          /* 0x04 */
-    MPI2_EVENT_HBD_DESCRIPTOR   Descriptor;         /* 0x08 */
-} MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY,
-  Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t;
-
-/* values for the DescriptorType field */
-#define MPI2_EVENT_HBD_DT_SAS               (0x01)
-
-
-
-/****************************************************************************
-*  EventAck message
-****************************************************************************/
-
-/* EventAck Request message */
-typedef struct _MPI2_EVENT_ACK_REQUEST
-{
-    U16                     Reserved1;                      /* 0x00 */
-    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 */
-    U16                     Event;                          /* 0x0C */
-    U16                     Reserved5;                      /* 0x0E */
-    U32                     EventContext;                   /* 0x10 */
-} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST,
-  Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t;
-
-
-/* EventAck Reply message */
-typedef struct _MPI2_EVENT_ACK_REPLY
-{
-    U16                     Reserved1;                      /* 0x00 */
-    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 */
-} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY,
-  Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t;
-
-
-/****************************************************************************
-*  SendHostMessage message
-****************************************************************************/
-
-/* SendHostMessage Request message */
-typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST {
-       U16                     HostDataLength;                 /* 0x00 */
-       U8                      ChainOffset;                    /* 0x02 */
-       U8                      Function;                       /* 0x03 */
-       U16                     Reserved1;                      /* 0x04 */
-       U8                      Reserved2;                      /* 0x06 */
-       U8                      MsgFlags;                       /* 0x07 */
-       U8                      VP_ID;                          /* 0x08 */
-       U8                      VF_ID;                          /* 0x09 */
-       U16                     Reserved3;                      /* 0x0A */
-       U8                      Reserved4;                      /* 0x0C */
-       U8                      DestVF_ID;                      /* 0x0D */
-       U16                     Reserved5;                      /* 0x0E */
-       U32                     Reserved6;                      /* 0x10 */
-       U32                     Reserved7;                      /* 0x14 */
-       U32                     Reserved8;                      /* 0x18 */
-       U32                     Reserved9;                      /* 0x1C */
-       U32                     Reserved10;                     /* 0x20 */
-       U32                     HostData[1];                    /* 0x24 */
-} MPI2_SEND_HOST_MESSAGE_REQUEST,
-MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST,
-Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t;
-
-
-/* SendHostMessage Reply message */
-typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY {
-       U16                     HostDataLength;                 /* 0x00 */
-       U8                      MsgLength;                      /* 0x02 */
-       U8                      Function;                       /* 0x03 */
-       U16                     Reserved1;                      /* 0x04 */
-       U8                      Reserved2;                      /* 0x06 */
-       U8                      MsgFlags;                       /* 0x07 */
-       U8                      VP_ID;                          /* 0x08 */
-       U8                      VF_ID;                          /* 0x09 */
-       U16                     Reserved3;                      /* 0x0A */
-       U16                     Reserved4;                      /* 0x0C */
-       U16                     IOCStatus;                      /* 0x0E */
-       U32                     IOCLogInfo;                     /* 0x10 */
-} MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY,
-Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t;
-
-
-/****************************************************************************
-*  FWDownload message
-****************************************************************************/
-
-/* FWDownload Request message */
-typedef struct _MPI2_FW_DOWNLOAD_REQUEST
-{
-    U8                      ImageType;                  /* 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                     TotalImageSize;             /* 0x0C */
-    U32                     Reserved5;                  /* 0x10 */
-    MPI2_MPI_SGE_UNION      SGL;                        /* 0x14 */
-} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST,
-  Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest;
-
-#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT   (0x01)
-
-#define MPI2_FW_DOWNLOAD_ITYPE_FW                   (0x01)
-#define MPI2_FW_DOWNLOAD_ITYPE_BIOS                 (0x02)
-#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING        (0x06)
-#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1             (0x07)
-#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2             (0x08)
-#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID             (0x09)
-#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE             (0x0A)
-#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK    (0x0B)
-#define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY           (0x0C)
-#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
-
-/* FWDownload TransactionContext Element */
-typedef struct _MPI2_FW_DOWNLOAD_TCSGE
-{
-    U8                      Reserved1;                  /* 0x00 */
-    U8                      ContextSize;                /* 0x01 */
-    U8                      DetailsLength;              /* 0x02 */
-    U8                      Flags;                      /* 0x03 */
-    U32                     Reserved2;                  /* 0x04 */
-    U32                     ImageOffset;                /* 0x08 */
-    U32                     ImageSize;                  /* 0x0C */
-} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE,
-  Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t;
-
-/* FWDownload Reply message */
-typedef struct _MPI2_FW_DOWNLOAD_REPLY
-{
-    U8                      ImageType;                  /* 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 */
-} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY,
-  Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t;
-
-
-/****************************************************************************
-*  FWUpload message
-****************************************************************************/
-
-/* FWUpload Request message */
-typedef struct _MPI2_FW_UPLOAD_REQUEST
-{
-    U8                      ImageType;                  /* 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 */
-    MPI2_MPI_SGE_UNION      SGL;                        /* 0x14 */
-} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST,
-  Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t;
-
-#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT         (0x00)
-#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH           (0x01)
-#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH         (0x02)
-#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP          (0x05)
-#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING      (0x06)
-#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1           (0x07)
-#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2           (0x08)
-#define MPI2_FW_UPLOAD_ITYPE_MEGARAID           (0x09)
-#define MPI2_FW_UPLOAD_ITYPE_COMPLETE           (0x0A)
-#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK  (0x0B)
-
-typedef struct _MPI2_FW_UPLOAD_TCSGE
-{
-    U8                      Reserved1;                  /* 0x00 */
-    U8                      ContextSize;                /* 0x01 */
-    U8                      DetailsLength;              /* 0x02 */
-    U8                      Flags;                      /* 0x03 */
-    U32                     Reserved2;                  /* 0x04 */
-    U32                     ImageOffset;                /* 0x08 */
-    U32                     ImageSize;                  /* 0x0C */
-} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE,
-  Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t;
-
-/* FWUpload Reply message */
-typedef struct _MPI2_FW_UPLOAD_REPLY
-{
-    U8                      ImageType;                  /* 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                     ActualImageSize;            /* 0x14 */
-} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY,
-  Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t;
-
-
-/* FW Image Header */
-typedef struct _MPI2_FW_IMAGE_HEADER
-{
-    U32                     Signature;                  /* 0x00 */
-    U32                     Signature0;                 /* 0x04 */
-    U32                     Signature1;                 /* 0x08 */
-    U32                     Signature2;                 /* 0x0C */
-    MPI2_VERSION_UNION      MPIVersion;                 /* 0x10 */
-    MPI2_VERSION_UNION      FWVersion;                  /* 0x14 */
-    MPI2_VERSION_UNION      NVDATAVersion;              /* 0x18 */
-    MPI2_VERSION_UNION      PackageVersion;             /* 0x1C */
-    U16                     VendorID;                   /* 0x20 */
-    U16                     ProductID;                  /* 0x22 */
-    U16                     ProtocolFlags;              /* 0x24 */
-    U16                     Reserved26;                 /* 0x26 */
-    U32                     IOCCapabilities;            /* 0x28 */
-    U32                     ImageSize;                  /* 0x2C */
-    U32                     NextImageHeaderOffset;      /* 0x30 */
-    U32                     Checksum;                   /* 0x34 */
-    U32                     Reserved38;                 /* 0x38 */
-    U32                     Reserved3C;                 /* 0x3C */
-    U32                     Reserved40;                 /* 0x40 */
-    U32                     Reserved44;                 /* 0x44 */
-    U32                     Reserved48;                 /* 0x48 */
-    U32                     Reserved4C;                 /* 0x4C */
-    U32                     Reserved50;                 /* 0x50 */
-    U32                     Reserved54;                 /* 0x54 */
-    U32                     Reserved58;                 /* 0x58 */
-    U32                     Reserved5C;                 /* 0x5C */
-    U32                     Reserved60;                 /* 0x60 */
-    U32                     FirmwareVersionNameWhat;    /* 0x64 */
-    U8                      FirmwareVersionName[32];    /* 0x68 */
-    U32                     VendorNameWhat;             /* 0x88 */
-    U8                      VendorName[32];             /* 0x8C */
-    U32                     PackageNameWhat;            /* 0x88 */
-    U8                      PackageName[32];            /* 0x8C */
-    U32                     ReservedD0;                 /* 0xD0 */
-    U32                     ReservedD4;                 /* 0xD4 */
-    U32                     ReservedD8;                 /* 0xD8 */
-    U32                     ReservedDC;                 /* 0xDC */
-    U32                     ReservedE0;                 /* 0xE0 */
-    U32                     ReservedE4;                 /* 0xE4 */
-    U32                     ReservedE8;                 /* 0xE8 */
-    U32                     ReservedEC;                 /* 0xEC */
-    U32                     ReservedF0;                 /* 0xF0 */
-    U32                     ReservedF4;                 /* 0xF4 */
-    U32                     ReservedF8;                 /* 0xF8 */
-    U32                     ReservedFC;                 /* 0xFC */
-} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER,
-  Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t;
-
-/* Signature field */
-#define MPI2_FW_HEADER_SIGNATURE_OFFSET         (0x00)
-#define MPI2_FW_HEADER_SIGNATURE_MASK           (0xFF000000)
-#define MPI2_FW_HEADER_SIGNATURE                (0xEA000000)
-
-/* Signature0 field */
-#define MPI2_FW_HEADER_SIGNATURE0_OFFSET        (0x04)
-#define MPI2_FW_HEADER_SIGNATURE0               (0x5AFAA55A)
-
-/* Signature1 field */
-#define MPI2_FW_HEADER_SIGNATURE1_OFFSET        (0x08)
-#define MPI2_FW_HEADER_SIGNATURE1               (0xA55AFAA5)
-
-/* Signature2 field */
-#define MPI2_FW_HEADER_SIGNATURE2_OFFSET        (0x0C)
-#define MPI2_FW_HEADER_SIGNATURE2               (0x5AA55AFA)
-
-
-/* defines for using the ProductID field */
-#define MPI2_FW_HEADER_PID_TYPE_MASK            (0xF000)
-#define MPI2_FW_HEADER_PID_TYPE_SAS             (0x2000)
-
-#define MPI2_FW_HEADER_PID_PROD_MASK                    (0x0F00)
-#define MPI2_FW_HEADER_PID_PROD_A                       (0x0000)
-#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI   (0x0200)
-#define MPI2_FW_HEADER_PID_PROD_IR_SCSI                 (0x0700)
-
-
-#define MPI2_FW_HEADER_PID_FAMILY_MASK          (0x00FF)
-/* SAS */
-#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS      (0x0013)
-#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS      (0x0014)
-
-/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
-
-/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
-
-
-#define MPI2_FW_HEADER_IMAGESIZE_OFFSET         (0x2C)
-#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET         (0x30)
-#define MPI2_FW_HEADER_VERNMHWAT_OFFSET         (0x64)
-
-#define MPI2_FW_HEADER_WHAT_SIGNATURE           (0x29232840)
-
-#define MPI2_FW_HEADER_SIZE                     (0x100)
-
-
-/* Extended Image Header */
-typedef struct _MPI2_EXT_IMAGE_HEADER
-
-{
-    U8                      ImageType;                  /* 0x00 */
-    U8                      Reserved1;                  /* 0x01 */
-    U16                     Reserved2;                  /* 0x02 */
-    U32                     Checksum;                   /* 0x04 */
-    U32                     ImageSize;                  /* 0x08 */
-    U32                     NextImageHeaderOffset;      /* 0x0C */
-    U32                     PackageVersion;             /* 0x10 */
-    U32                     Reserved3;                  /* 0x14 */
-    U32                     Reserved4;                  /* 0x18 */
-    U32                     Reserved5;                  /* 0x1C */
-    U8                      IdentifyString[32];         /* 0x20 */
-} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER,
-  Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t;
-
-/* useful offsets */
-#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET         (0x00)
-#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET         (0x08)
-#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET         (0x0C)
-
-#define MPI2_EXT_IMAGE_HEADER_SIZE              (0x40)
-
-/* defines for the ImageType field */
-#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED             (0x00)
-#define MPI2_EXT_IMAGE_TYPE_FW                      (0x01)
-#define MPI2_EXT_IMAGE_TYPE_NVDATA                  (0x03)
-#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER              (0x04)
-#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION          (0x05)
-#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT            (0x06)
-#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES       (0x07)
-#define MPI2_EXT_IMAGE_TYPE_MEGARAID                (0x08)
-#define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH          (0x09)
-#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC    (0x80)
-#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC    (0xFF)
-#define MPI2_EXT_IMAGE_TYPE_MAX                   \
-       (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC)      /* deprecated */
-
-
-
-/* FLASH Layout Extended Image Data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check RegionsPerLayout at runtime.
- */
-#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
-#define MPI2_FLASH_NUMBER_OF_REGIONS        (1)
-#endif
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumberOfLayouts at runtime.
- */
-#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
-#define MPI2_FLASH_NUMBER_OF_LAYOUTS        (1)
-#endif
-
-typedef struct _MPI2_FLASH_REGION
-{
-    U8                      RegionType;                 /* 0x00 */
-    U8                      Reserved1;                  /* 0x01 */
-    U16                     Reserved2;                  /* 0x02 */
-    U32                     RegionOffset;               /* 0x04 */
-    U32                     RegionSize;                 /* 0x08 */
-    U32                     Reserved3;                  /* 0x0C */
-} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION,
-  Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t;
-
-typedef struct _MPI2_FLASH_LAYOUT
-{
-    U32                     FlashSize;                  /* 0x00 */
-    U32                     Reserved1;                  /* 0x04 */
-    U32                     Reserved2;                  /* 0x08 */
-    U32                     Reserved3;                  /* 0x0C */
-    MPI2_FLASH_REGION       Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */
-} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT,
-  Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t;
-
-typedef struct _MPI2_FLASH_LAYOUT_DATA
-{
-    U8                      ImageRevision;              /* 0x00 */
-    U8                      Reserved1;                  /* 0x01 */
-    U8                      SizeOfRegion;               /* 0x02 */
-    U8                      Reserved2;                  /* 0x03 */
-    U16                     NumberOfLayouts;            /* 0x04 */
-    U16                     RegionsPerLayout;           /* 0x06 */
-    U16                     MinimumSectorAlignment;     /* 0x08 */
-    U16                     Reserved3;                  /* 0x0A */
-    U32                     Reserved4;                  /* 0x0C */
-    MPI2_FLASH_LAYOUT       Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */
-} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA,
-  Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t;
-
-/* defines for the RegionType field */
-#define MPI2_FLASH_REGION_UNUSED                (0x00)
-#define MPI2_FLASH_REGION_FIRMWARE              (0x01)
-#define MPI2_FLASH_REGION_BIOS                  (0x02)
-#define MPI2_FLASH_REGION_NVDATA                (0x03)
-#define MPI2_FLASH_REGION_FIRMWARE_BACKUP       (0x05)
-#define MPI2_FLASH_REGION_MFG_INFORMATION       (0x06)
-#define MPI2_FLASH_REGION_CONFIG_1              (0x07)
-#define MPI2_FLASH_REGION_CONFIG_2              (0x08)
-#define MPI2_FLASH_REGION_MEGARAID              (0x09)
-#define MPI2_FLASH_REGION_INIT                  (0x0A)
-
-/* ImageRevision */
-#define MPI2_FLASH_LAYOUT_IMAGE_REVISION        (0x00)
-
-
-
-/* Supported Devices Extended Image Data */
-
-/*
- * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
- * one and check NumberOfDevices at runtime.
- */
-#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
-#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES    (1)
-#endif
-
-typedef struct _MPI2_SUPPORTED_DEVICE
-{
-    U16                     DeviceID;                   /* 0x00 */
-    U16                     VendorID;                   /* 0x02 */
-    U16                     DeviceIDMask;               /* 0x04 */
-    U16                     Reserved1;                  /* 0x06 */
-    U8                      LowPCIRev;                  /* 0x08 */
-    U8                      HighPCIRev;                 /* 0x09 */
-    U16                     Reserved2;                  /* 0x0A */
-    U32                     Reserved3;                  /* 0x0C */
-} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE,
-  Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t;
-
-typedef struct _MPI2_SUPPORTED_DEVICES_DATA
-{
-    U8                      ImageRevision;              /* 0x00 */
-    U8                      Reserved1;                  /* 0x01 */
-    U8                      NumberOfDevices;            /* 0x02 */
-    U8                      Reserved2;                  /* 0x03 */
-    U32                     Reserved3;                  /* 0x04 */
-    MPI2_SUPPORTED_DEVICE   SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */
-} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA,
-  Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t;
-
-/* ImageRevision */
-#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION   (0x00)
-
-
-/* Init Extended Image Data */
-
-typedef struct _MPI2_INIT_IMAGE_FOOTER
-
-{
-    U32                     BootFlags;                  /* 0x00 */
-    U32                     ImageSize;                  /* 0x04 */
-    U32                     Signature0;                 /* 0x08 */
-    U32                     Signature1;                 /* 0x0C */
-    U32                     Signature2;                 /* 0x10 */
-    U32                     ResetVector;                /* 0x14 */
-} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER,
-  Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t;
-
-/* defines for the BootFlags field */
-#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET        (0x00)
-
-/* defines for the ImageSize field */
-#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET        (0x04)
-
-/* defines for the Signature0 field */
-#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET       (0x08)
-#define MPI2_INIT_IMAGE_SIGNATURE0              (0x5AA55AEA)
-
-/* defines for the Signature1 field */
-#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET       (0x0C)
-#define MPI2_INIT_IMAGE_SIGNATURE1              (0xA55AEAA5)
-
-/* defines for the Signature2 field */
-#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET       (0x10)
-#define MPI2_INIT_IMAGE_SIGNATURE2              (0x5AEAA55A)
-
-/* Signature fields as individual bytes */
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0        (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1        (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2        (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3        (0x5A)
-
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4        (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5        (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6        (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7        (0xA5)
-
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8        (0x5A)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9        (0xA5)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A        (0xEA)
-#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B        (0x5A)
-
-/* defines for the ResetVector field */
-#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET      (0x14)
-
-
-/* Encrypted Hash Extended Image Data */
-
-typedef struct _MPI25_ENCRYPTED_HASH_ENTRY {
-       U8                  HashImageType;          /* 0x00 */
-       U8                  HashAlgorithm;          /* 0x01 */
-       U8                  EncryptionAlgorithm;    /* 0x02 */
-       U8                  Reserved1;              /* 0x03 */
-       U32                 Reserved2;              /* 0x04 */
-       U32                 EncryptedHash[1];       /* 0x08 */
-} MPI25_ENCRYPTED_HASH_ENTRY, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_ENTRY,
-Mpi25EncryptedHashEntry_t, MPI2_POINTER pMpi25EncryptedHashEntry_t;
-
-/* values for HashImageType */
-#define MPI25_HASH_IMAGE_TYPE_UNUSED            (0x00)
-#define MPI25_HASH_IMAGE_TYPE_FIRMWARE          (0x01)
-#define MPI25_HASH_IMAGE_TYPE_BIOS              (0x02)
-
-/* values for HashAlgorithm */
-#define MPI25_HASH_ALGORITHM_UNUSED             (0x00)
-#define MPI25_HASH_ALGORITHM_SHA256             (0x01)
-
-/* values for EncryptionAlgorithm */
-#define MPI25_ENCRYPTION_ALG_UNUSED             (0x00)
-#define MPI25_ENCRYPTION_ALG_RSA256             (0x01)
-
-typedef struct _MPI25_ENCRYPTED_HASH_DATA {
-       U8                              ImageVersion;           /* 0x00 */
-       U8                              NumHash;                /* 0x01 */
-       U16                             Reserved1;              /* 0x02 */
-       U32                             Reserved2;              /* 0x04 */
-       MPI25_ENCRYPTED_HASH_ENTRY      EncryptedHashEntry[1];  /* 0x08 */
-} MPI25_ENCRYPTED_HASH_DATA, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_DATA,
-Mpi25EncryptedHashData_t, MPI2_POINTER pMpi25EncryptedHashData_t;
-
-/****************************************************************************
-*  PowerManagementControl message
-****************************************************************************/
-
-/* PowerManagementControl Request message */
-typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST {
-    U8                      Feature;                    /* 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                      Parameter1;                 /* 0x0C */
-    U8                      Parameter2;                 /* 0x0D */
-    U8                      Parameter3;                 /* 0x0E */
-    U8                      Parameter4;                 /* 0x0F */
-    U32                     Reserved5;                  /* 0x10 */
-    U32                     Reserved6;                  /* 0x14 */
-} MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST,
-  Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t;
-
-/* defines for the Feature field */
-#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND       (0x01)
-#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION   (0x02)
-#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK               (0x03) /* obsolete */
-#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED               (0x04)
-#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC    (0x80)
-#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC    (0xFF)
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */
-/* Parameter1 contains a PHY number */
-/* Parameter2 indicates power condition action using these defines */
-#define MPI2_PM_CONTROL_PARAM2_PARTIAL                  (0x01)
-#define MPI2_PM_CONTROL_PARAM2_SLUMBER                  (0x02)
-#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT            (0x03)
-/* Parameter3 and Parameter4 are reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION
- *  Feature */
-/* Parameter1 contains SAS port width modulation group number */
-/* Parameter2 indicates IOC action using these defines */
-#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP        (0x01)
-#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION        (0x02)
-#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP     (0x03)
-/* Parameter3 indicates desired modulation level using these defines */
-#define MPI2_PM_CONTROL_PARAM3_25_PERCENT               (0x00)
-#define MPI2_PM_CONTROL_PARAM3_50_PERCENT               (0x01)
-#define MPI2_PM_CONTROL_PARAM3_75_PERCENT               (0x02)
-#define MPI2_PM_CONTROL_PARAM3_100_PERCENT              (0x03)
-/* Parameter4 is reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */
-/* Parameter1 indicates desired PCIe link speed using these defines */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS            (0x00) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS            (0x01) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS            (0x02) /* obsolete */
-/* Parameter2 indicates desired PCIe link width using these defines */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1                 (0x01) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2                 (0x02) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4                 (0x04) /* obsolete */
-#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8                 (0x08) /* obsolete */
-/* Parameter3 and Parameter4 are reserved */
-
-/* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */
-/* Parameter1 indicates desired IOC hardware clock speed using these defines */
-#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED           (0x01)
-#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED           (0x02)
-#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED        (0x04)
-#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED         (0x08)
-/* Parameter2, Parameter3, and Parameter4 are reserved */
-
-
-/* PowerManagementControl Reply message */
-typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY {
-    U8                      Feature;                    /* 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 */
-} MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
-  Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
deleted file mode 100644 (file)
index 7efa58f..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_raid.h
- *          Title:  MPI Integrated RAID messages and structures
- *  Creation Date:  April 26, 2007
- *
- *    mpi2_raid.h Version:  02.00.10
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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.
- *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
- *                      VolumeCreationFlags and marked the old one as obsolete.
- *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
- *  08-24-10  02.00.06  Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with
- *                      related structures and defines.
- *                      Added product-specific range to RAID Action values.
- *  02-06-12  02.00.08  Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN.
- *  07-26-12  02.00.09  Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR.
- *                      Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define.
- *  04-17-13  02.00.10  Added MPI25_RAID_ACTION_ADATA_ALLOW_PI.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_RAID_H
-#define MPI2_RAID_H
-
-/*****************************************************************************
-*
-*               Integrated RAID Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  RAID Action messages
-****************************************************************************/
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */
-#define MPI25_RAID_ACTION_ADATA_ALLOW_PI            (0x80000000)
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
-#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0            (0x00000000)
-#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0            (0x00000001)
-
-/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
-#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD  (0x00000001)
-
-/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
-typedef struct _MPI2_RAID_ACTION_RATE_DATA
-{
-    U8              RateToChange;               /* 0x00 */
-    U8              RateOrMode;                 /* 0x01 */
-    U16             DataScrubDuration;          /* 0x02 */
-} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
-  Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
-
-#define MPI2_RAID_ACTION_SET_RATE_RESYNC            (0x00)
-#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB        (0x01)
-#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE    (0x02)
-
-/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
-typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
-{
-    U8              RAIDFunction;                       /* 0x00 */
-    U8              Flags;                              /* 0x01 */
-    U16             Reserved1;                          /* 0x02 */
-} MPI2_RAID_ACTION_START_RAID_FUNCTION,
-  MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
-  Mpi2RaidActionStartRaidFunction_t,
-  MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
-
-/* defines for the RAIDFunction field */
-#define MPI2_RAID_ACTION_START_BACKGROUND_INIT      (0x00)
-#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
-#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK    (0x02)
-
-/* defines for the Flags field */
-#define MPI2_RAID_ACTION_START_NEW                  (0x00)
-#define MPI2_RAID_ACTION_START_RESUME               (0x01)
-
-/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
-typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
-{
-    U8              RAIDFunction;                       /* 0x00 */
-    U8              Flags;                              /* 0x01 */
-    U16             Reserved1;                          /* 0x02 */
-} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
-  MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
-  Mpi2RaidActionStopRaidFunction_t,
-  MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
-
-/* defines for the RAIDFunction field */
-#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT       (0x00)
-#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION  (0x01)
-#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK     (0x02)
-
-/* defines for the Flags field */
-#define MPI2_RAID_ACTION_STOP_ABORT                 (0x00)
-#define MPI2_RAID_ACTION_STOP_PAUSE                 (0x01)
-
-/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
-typedef struct _MPI2_RAID_ACTION_HOT_SPARE
-{
-    U8              HotSparePool;               /* 0x00 */
-    U8              Reserved1;                  /* 0x01 */
-    U16             DevHandle;                  /* 0x02 */
-} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
-  Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
-
-/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
-typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
-{
-    U8              Flags;                              /* 0x00 */
-    U8              DeviceFirmwareUpdateModeTimeout;    /* 0x01 */
-    U16             Reserved1;                          /* 0x02 */
-} MPI2_RAID_ACTION_FW_UPDATE_MODE,
-  MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
-  Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
-
-/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
-#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE        (0x00)
-#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE         (0x01)
-
-typedef union _MPI2_RAID_ACTION_DATA
-{
-    U32                                     Word;
-    MPI2_RAID_ACTION_RATE_DATA              Rates;
-    MPI2_RAID_ACTION_START_RAID_FUNCTION    StartRaidFunction;
-    MPI2_RAID_ACTION_STOP_RAID_FUNCTION     StopRaidFunction;
-    MPI2_RAID_ACTION_HOT_SPARE              HotSpare;
-    MPI2_RAID_ACTION_FW_UPDATE_MODE         FwUpdateMode;
-} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
-  Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
-
-
-/* RAID Action Request Message */
-typedef struct _MPI2_RAID_ACTION_REQUEST
-{
-    U8                      Action;                         /* 0x00 */
-    U8                      Reserved1;                      /* 0x01 */
-    U8                      ChainOffset;                    /* 0x02 */
-    U8                      Function;                       /* 0x03 */
-    U16                     VolDevHandle;                   /* 0x04 */
-    U8                      PhysDiskNum;                    /* 0x06 */
-    U8                      MsgFlags;                       /* 0x07 */
-    U8                      VP_ID;                          /* 0x08 */
-    U8                      VF_ID;                          /* 0x09 */
-    U16                     Reserved2;                      /* 0x0A */
-    U32                     Reserved3;                      /* 0x0C */
-    MPI2_RAID_ACTION_DATA   ActionDataWord;                 /* 0x10 */
-    MPI2_SGE_SIMPLE_UNION   ActionDataSGE;                  /* 0x14 */
-} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
-  Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
-
-/* RAID Action request Action values */
-
-#define MPI2_RAID_ACTION_INDICATOR_STRUCT           (0x01)
-#define MPI2_RAID_ACTION_CREATE_VOLUME              (0x02)
-#define MPI2_RAID_ACTION_DELETE_VOLUME              (0x03)
-#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES        (0x04)
-#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES         (0x05)
-#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE           (0x0A)
-#define MPI2_RAID_ACTION_PHYSDISK_ONLINE            (0x0B)
-#define MPI2_RAID_ACTION_FAIL_PHYSDISK              (0x0F)
-#define MPI2_RAID_ACTION_ACTIVATE_VOLUME            (0x11)
-#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE      (0x15)
-#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE     (0x17)
-#define MPI2_RAID_ACTION_SET_VOLUME_NAME            (0x18)
-#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE     (0x19)
-#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME       (0x1C)
-#define MPI2_RAID_ACTION_CREATE_HOT_SPARE           (0x1D)
-#define MPI2_RAID_ACTION_DELETE_HOT_SPARE           (0x1E)
-#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED  (0x20)
-#define MPI2_RAID_ACTION_START_RAID_FUNCTION        (0x21)
-#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION         (0x22)
-#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK        (0x23)
-#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN            (0x24)
-#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC       (0x80)
-#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC       (0xFF)
-
-/* RAID Volume Creation Structure */
-
-/*
- * The following define can be customized for the targeted product.
- */
-#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
-#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS        (1)
-#endif
-
-typedef struct _MPI2_RAID_VOLUME_PHYSDISK
-{
-    U8                      RAIDSetNum;                     /* 0x00 */
-    U8                      PhysDiskMap;                    /* 0x01 */
-    U16                     PhysDiskDevHandle;              /* 0x02 */
-} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
-  Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
-
-/* defines for the PhysDiskMap field */
-#define MPI2_RAIDACTION_PHYSDISK_PRIMARY            (0x01)
-#define MPI2_RAIDACTION_PHYSDISK_SECONDARY          (0x02)
-
-typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
-{
-    U8                          NumPhysDisks;               /* 0x00 */
-    U8                          VolumeType;                 /* 0x01 */
-    U16                         Reserved1;                  /* 0x02 */
-    U32                         VolumeCreationFlags;        /* 0x04 */
-    U32                         VolumeSettings;             /* 0x08 */
-    U8                          Reserved2;                  /* 0x0C */
-    U8                          ResyncRate;                 /* 0x0D */
-    U16                         DataScrubDuration;          /* 0x0E */
-    U64                         VolumeMaxLBA;               /* 0x10 */
-    U32                         StripeSize;                 /* 0x18 */
-    U8                          Name[16];                   /* 0x1C */
-    MPI2_RAID_VOLUME_PHYSDISK   PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
-} MPI2_RAID_VOLUME_CREATION_STRUCT,
-  MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
-  Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
-
-/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
-
-/* defines for the VolumeCreationFlags field */
-#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS     (0x80000000)
-#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT      (0x00000004)
-#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT       (0x00000002)
-#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA         (0x00000001)
-/* The following is an obsolete define.
- * It must be shifted left 24 bits in order to set the proper bit.
- */
-#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
-
-
-/* RAID Online Capacity Expansion Structure */
-
-typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
-{
-    U32                     Flags;                          /* 0x00 */
-    U16                     DevHandle0;                     /* 0x04 */
-    U16                     Reserved1;                      /* 0x06 */
-    U16                     DevHandle1;                     /* 0x08 */
-    U16                     Reserved2;                      /* 0x0A */
-} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
-  MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
-  Mpi2RaidOnlineCapacityExpansion_t,
-  MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
-
-/* RAID Compatibility Input Structure */
-
-typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT {
-       U16                     SourceDevHandle;               /* 0x00 */
-       U16                     CandidateDevHandle;             /* 0x02 */
-       U32                     Flags;                          /* 0x04 */
-       U32                     Reserved1;                      /* 0x08 */
-       U32                     Reserved2;                      /* 0x0C */
-} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
-MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT,
-Mpi2RaidCompatibilityInputStruct_t,
-MPI2_POINTER pMpi2RaidCompatibilityInputStruct_t;
-
-/* defines for RAID Compatibility Structure Flags field */
-#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG      (0x00000002)
-#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG    (0x00000001)
-
-
-/* RAID Volume Indicator Structure */
-
-typedef struct _MPI2_RAID_VOL_INDICATOR
-{
-    U64                     TotalBlocks;                    /* 0x00 */
-    U64                     BlocksRemaining;                /* 0x08 */
-    U32                     Flags;                          /* 0x10 */
-       U32                     ElapsedSeconds;                 /* 0x14 */
-} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
-  Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
-
-/* defines for RAID Volume Indicator Flags field */
-#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID   (0x80000000)
-
-#define MPI2_RAID_VOL_FLAGS_OP_MASK                 (0x0000000F)
-#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT      (0x00000000)
-#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
-#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK    (0x00000002)
-#define MPI2_RAID_VOL_FLAGS_OP_RESYNC               (0x00000003)
-#define MPI2_RAID_VOL_FLAGS_OP_MDC                  (0x00000004)
-
-/* RAID Compatibility Result Structure */
-
-typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT {
-       U8                      State;                          /* 0x00 */
-       U8                      Reserved1;                      /* 0x01 */
-       U16                     Reserved2;                      /* 0x02 */
-       U32                     GenericAttributes;              /* 0x04 */
-       U32                     OEMSpecificAttributes;          /* 0x08 */
-       U32                     Reserved3;                      /* 0x0C */
-       U32                     Reserved4;                      /* 0x10 */
-} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
-MPI2_POINTER PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT,
-Mpi2RaidCompatibilityResultStruct_t,
-MPI2_POINTER pMpi2RaidCompatibilityResultStruct_t;
-
-/* defines for RAID Compatibility Result Structure State field */
-#define MPI2_RAID_COMPAT_STATE_COMPATIBLE           (0x00)
-#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE       (0x01)
-
-/* defines for RAID Compatibility Result Structure GenericAttributes field */
-#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR            (0x00000010)
-
-#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK           (0x0000000C)
-#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE    (0x00000008)
-#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE      (0x00000004)
-
-#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK        (0x00000003)
-#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL         (0x00000002)
-#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL        (0x00000001)
-
-/* RAID Action Reply ActionData union */
-typedef union _MPI2_RAID_ACTION_REPLY_DATA
-{
-       U32                                     Word[6];
-       MPI2_RAID_VOL_INDICATOR                 RaidVolumeIndicator;
-       U16                                     VolDevHandle;
-       U8                                      VolumeState;
-       U8                                      PhysDiskNum;
-       MPI2_RAID_COMPATIBILITY_RESULT_STRUCT   RaidCompatibilityResult;
-} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
-  Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
-
-/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
-
-
-/* RAID Action Reply Message */
-typedef struct _MPI2_RAID_ACTION_REPLY
-{
-    U8                          Action;                     /* 0x00 */
-    U8                          Reserved1;                  /* 0x01 */
-    U8                          MsgLength;                  /* 0x02 */
-    U8                          Function;                   /* 0x03 */
-    U16                         VolDevHandle;               /* 0x04 */
-    U8                          PhysDiskNum;                /* 0x06 */
-    U8                          MsgFlags;                   /* 0x07 */
-    U8                          VP_ID;                      /* 0x08 */
-    U8                          VF_ID;                      /* 0x09 */
-    U16                         Reserved2;                  /* 0x0A */
-    U16                         Reserved3;                  /* 0x0C */
-    U16                         IOCStatus;                  /* 0x0E */
-    U32                         IOCLogInfo;                 /* 0x10 */
-    MPI2_RAID_ACTION_REPLY_DATA ActionData;                 /* 0x14 */
-} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
-  Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
deleted file mode 100644 (file)
index 45b6fa1..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_sas.h
- *          Title:  MPI Serial Attached SCSI structures and definitions
- *  Creation Date:  February 9, 2007
- *
- *  mpi2_sas.h Version:  02.00.05
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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.
- *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
- *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
- *  05-12-10  02.00.04  Modified some comments.
- *  08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_SAS_H
-#define MPI2_SAS_H
-
-/*
- * Values for SASStatus.
- */
-#define MPI2_SASSTATUS_SUCCESS                          (0x00)
-#define MPI2_SASSTATUS_UNKNOWN_ERROR                    (0x01)
-#define MPI2_SASSTATUS_INVALID_FRAME                    (0x02)
-#define MPI2_SASSTATUS_UTC_BAD_DEST                     (0x03)
-#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED               (0x04)
-#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED   (0x05)
-#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST           (0x06)
-#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED       (0x07)
-#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY           (0x08)
-#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION            (0x09)
-#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT           (0x0A)
-#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT            (0x0B)
-#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA    (0x0C)
-#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR    (0x0D)
-#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED            (0x0E)
-#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH       (0x0F)
-#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA          (0x10)
-#define MPI2_SASSTATUS_DATA_OFFSET_ERROR                (0x11)
-#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED                (0x12)
-#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED           (0x13)
-#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT       (0x14)
-
-
-/*
- * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
- * data and SAS Configuration pages.
- */
-#define MPI2_SAS_DEVICE_INFO_SEP                (0x00004000)
-#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE       (0x00002000)
-#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE         (0x00001000)
-#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH      (0x00000800)
-#define MPI2_SAS_DEVICE_INFO_SSP_TARGET         (0x00000400)
-#define MPI2_SAS_DEVICE_INFO_STP_TARGET         (0x00000200)
-#define MPI2_SAS_DEVICE_INFO_SMP_TARGET         (0x00000100)
-#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE        (0x00000080)
-#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR      (0x00000040)
-#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR      (0x00000020)
-#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR      (0x00000010)
-#define MPI2_SAS_DEVICE_INFO_SATA_HOST          (0x00000008)
-
-#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE   (0x00000007)
-#define MPI2_SAS_DEVICE_INFO_NO_DEVICE          (0x00000000)
-#define MPI2_SAS_DEVICE_INFO_END_DEVICE         (0x00000001)
-#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER      (0x00000002)
-#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER    (0x00000003)
-
-
-/*****************************************************************************
-*
-*        SAS Messages
-*
-*****************************************************************************/
-
-/****************************************************************************
-*  SMP Passthrough messages
-****************************************************************************/
-
-/* SMP Passthrough Request Message */
-typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
-{
-    U8                      PassthroughFlags;   /* 0x00 */
-    U8                      PhysicalPort;       /* 0x01 */
-    U8                      ChainOffset;        /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     RequestDataLength;  /* 0x04 */
-    U8                      SGLFlags;           /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved1;          /* 0x0A */
-    U32                     Reserved2;          /* 0x0C */
-    U64                     SASAddress;         /* 0x10 */
-    U32                     Reserved3;          /* 0x18 */
-    U32                     Reserved4;          /* 0x1C */
-    MPI2_SIMPLE_SGE_UNION   SGL;                /* 0x20 */
-} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
-  Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE      (0x80)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* SMP Passthrough Reply Message */
-typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
-{
-    U8                      PassthroughFlags;   /* 0x00 */
-    U8                      PhysicalPort;       /* 0x01 */
-    U8                      MsgLength;          /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     ResponseDataLength; /* 0x04 */
-    U8                      SGLFlags;           /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved1;          /* 0x0A */
-    U8                      Reserved2;          /* 0x0C */
-    U8                      SASStatus;          /* 0x0D */
-    U16                     IOCStatus;          /* 0x0E */
-    U32                     IOCLogInfo;         /* 0x10 */
-    U32                     Reserved3;          /* 0x14 */
-    U8                      ResponseData[4];    /* 0x18 */
-} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
-  Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE    (0x80)
-
-/* values for SASStatus field are at the top of this file */
-
-
-/****************************************************************************
-*  SATA Passthrough messages
-****************************************************************************/
-
-/* SATA Passthrough Request Message */
-typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
-{
-    U16                     DevHandle;          /* 0x00 */
-    U8                      ChainOffset;        /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     PassthroughFlags;   /* 0x04 */
-    U8                      SGLFlags;           /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved1;          /* 0x0A */
-    U32                     Reserved2;          /* 0x0C */
-    U32                     Reserved3;          /* 0x10 */
-    U32                     Reserved4;          /* 0x14 */
-    U32                     DataLength;         /* 0x18 */
-    U8                      CommandFIS[20];     /* 0x1C */
-    MPI2_SGE_IO_UNION       SGL;                /* 0x30 */
-} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
-  Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
-
-/* values for PassthroughFlags field */
-#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG      (0x0100)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA               (0x0020)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO               (0x0010)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU    (0x0004)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE             (0x0002)
-#define MPI2_SATA_PT_REQ_PT_FLAGS_READ              (0x0001)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* SATA Passthrough Reply Message */
-typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
-{
-    U16                     DevHandle;          /* 0x00 */
-    U8                      MsgLength;          /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     PassthroughFlags;   /* 0x04 */
-    U8                      SGLFlags;           /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved1;          /* 0x0A */
-    U8                      Reserved2;          /* 0x0C */
-    U8                      SASStatus;          /* 0x0D */
-    U16                     IOCStatus;          /* 0x0E */
-    U32                     IOCLogInfo;         /* 0x10 */
-    U8                      StatusFIS[20];      /* 0x14 */
-    U32                     StatusControlRegisters; /* 0x28 */
-    U32                     TransferCount;      /* 0x2C */
-} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
-  Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
-
-/* values for SASStatus field are at the top of this file */
-
-
-/****************************************************************************
-*  SAS IO Unit Control messages
-****************************************************************************/
-
-/* SAS IO Unit Control Request Message */
-typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
-{
-    U8                      Operation;          /* 0x00 */
-    U8                      Reserved1;          /* 0x01 */
-    U8                      ChainOffset;        /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     DevHandle;          /* 0x04 */
-    U8                      IOCParameter;       /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved3;          /* 0x0A */
-    U16                     Reserved4;          /* 0x0C */
-    U8                      PhyNum;             /* 0x0E */
-    U8                      PrimFlags;          /* 0x0F */
-    U32                     Primitive;          /* 0x10 */
-    U8                      LookupMethod;       /* 0x14 */
-    U8                      Reserved5;          /* 0x15 */
-    U16                     SlotNumber;         /* 0x16 */
-    U64                     LookupAddress;      /* 0x18 */
-    U32                     IOCParameterValue;  /* 0x20 */
-    U32                     Reserved7;          /* 0x24 */
-    U32                     Reserved8;          /* 0x28 */
-} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
-  MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
-  Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
-
-/* values for the Operation field */
-#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT        (0x02)
-#define MPI2_SAS_OP_PHY_LINK_RESET              (0x06)
-#define MPI2_SAS_OP_PHY_HARD_RESET              (0x07)
-#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG         (0x08)
-#define MPI2_SAS_OP_SEND_PRIMITIVE              (0x0A)
-#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY        (0x0B)
-#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
-#define MPI2_SAS_OP_REMOVE_DEVICE               (0x0D)
-#define MPI2_SAS_OP_LOOKUP_MAPPING              (0x0E)
-#define MPI2_SAS_OP_SET_IOC_PARAMETER           (0x0F)
-#define MPI2_SAS_OP_DEV_ENABLE_NCQ              (0x14)
-#define MPI2_SAS_OP_DEV_DISABLE_NCQ             (0x15)
-#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN        (0x80)
-
-/* values for the PrimFlags field */
-#define MPI2_SAS_PRIMFLAGS_SINGLE               (0x08)
-#define MPI2_SAS_PRIMFLAGS_TRIPLE               (0x02)
-#define MPI2_SAS_PRIMFLAGS_REDUNDANT            (0x01)
-
-/* values for the LookupMethod field */
-#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS          (0x01)
-#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT   (0x02)
-#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME      (0x03)
-
-
-/* SAS IO Unit Control Reply Message */
-typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
-{
-    U8                      Operation;          /* 0x00 */
-    U8                      Reserved1;          /* 0x01 */
-    U8                      MsgLength;          /* 0x02 */
-    U8                      Function;           /* 0x03 */
-    U16                     DevHandle;          /* 0x04 */
-    U8                      IOCParameter;       /* 0x06 */
-    U8                      MsgFlags;           /* 0x07 */
-    U8                      VP_ID;              /* 0x08 */
-    U8                      VF_ID;              /* 0x09 */
-    U16                     Reserved3;          /* 0x0A */
-    U16                     Reserved4;          /* 0x0C */
-    U16                     IOCStatus;          /* 0x0E */
-    U32                     IOCLogInfo;         /* 0x10 */
-} MPI2_SAS_IOUNIT_CONTROL_REPLY,
-  MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
-  Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
-
-
-#endif
-
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
deleted file mode 100644 (file)
index 659b8ac..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_tool.h
- *          Title:  MPI diagnostic tool structures and definitions
- *  Creation Date:  March 26, 2007
- *
- *    mpi2_tool.h Version:  02.00.12
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  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.
- *  07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
- *                      and reply messages.
- *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
- *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
- *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
- *  08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
- *                      Post Request.
- *  05-25-11  02.00.07  Added Flags field and related defines to
- *                      MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST.
- *  07-26-12  02.00.10  Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that
- *                     it uses MPI Chain SGE as well as MPI Simple SGE.
- *  08-19-13  02.00.11  Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
- *  01-08-14  02.00.12  Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_TOOL_H
-#define MPI2_TOOL_H
-
-/*****************************************************************************
-*
-*               Toolbox Messages
-*
-*****************************************************************************/
-
-/* defines for the Tools */
-#define MPI2_TOOLBOX_CLEAN_TOOL                     (0x00)
-#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL               (0x01)
-#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL          (0x02)
-#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL          (0x03)
-#define MPI2_TOOLBOX_BEACON_TOOL                    (0x05)
-#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL            (0x06)
-#define MPI2_TOOLBOX_TEXT_DISPLAY_TOOL              (0x07)
-
-
-/****************************************************************************
-*  Toolbox reply
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_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 */
-} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY,
-  Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t;
-
-
-/****************************************************************************
-*  Toolbox Clean Tool request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_CLEAN_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                     Flags;                      /* 0x0C */
-   } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
-  Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t;
-
-/* values for the Flags field */
-#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES            (0x80000000)
-#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES   (0x40000000)
-#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES      (0x20000000)
-#define MPI2_TOOLBOX_CLEAN_FW_CURRENT               (0x10000000)
-#define MPI2_TOOLBOX_CLEAN_FW_BACKUP                (0x08000000)
-#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC   (0x04000000)
-#define MPI2_TOOLBOX_CLEAN_MEGARAID                 (0x02000000)
-#define MPI2_TOOLBOX_CLEAN_INITIALIZATION           (0x01000000)
-#define MPI2_TOOLBOX_CLEAN_FLASH                    (0x00000004)
-#define MPI2_TOOLBOX_CLEAN_SEEPROM                  (0x00000002)
-#define MPI2_TOOLBOX_CLEAN_NVSRAM                   (0x00000001)
-
-
-/****************************************************************************
-*  Toolbox Memory Move request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_MEM_MOVE_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 */
-    MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x0C */
-} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
-  Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
-
-
-/****************************************************************************
-*  Toolbox Diagnostic Data Upload request
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_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                     Flags;                      /* 0x10 */
-       U32                     DataLength;                 /* 0x14 */
-       MPI2_SGE_SIMPLE_UNION   SGL;                        /* 0x18 */
-} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
-MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST,
-Mpi2ToolboxDiagDataUploadRequest_t,
-MPI2_POINTER pMpi2ToolboxDiagDataUploadRequest_t;
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER {
-       U32                     DiagDataLength;             /* 00h */
-       U8                      FormatCode;                 /* 04h */
-       U8                      Reserved1;                  /* 05h */
-       U16                     Reserved2;                  /* 06h */
-} MPI2_DIAG_DATA_UPLOAD_HEADER, MPI2_POINTER PTR_MPI2_DIAG_DATA_UPLOAD_HEADER,
-Mpi2DiagDataUploadHeader_t, MPI2_POINTER pMpi2DiagDataUploadHeader_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                      Flags;                      /* 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)
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-/* values for the Flags field */
-#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE   (0x80)
-#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK         (0x07)
-
-/* 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
-****************************************************************************/
-
-typedef struct _MPI2_TOOLBOX_BEACON_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                      Reserved5;                  /* 0x0C */
-    U8                      PhysicalPort;               /* 0x0D */
-    U8                      Reserved6;                  /* 0x0E */
-    U8                      Flags;                      /* 0x0F */
-} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST,
-  Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t;
-
-/* values for the Flags field */
-#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF       (0x00)
-#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON        (0x01)
-
-
-/****************************************************************************
-*  Toolbox Diagnostic CLI Tool
-****************************************************************************/
-
-#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH    (0x5C)
-
-/* MPI v2.0 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_MPI_SGE_IO_UNION   SGL;                        /* 0x70 */
-} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
-  MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST,
-  Mpi2ToolboxDiagnosticCliRequest_t,
-  MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t;
-
-/* use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */
-
-
-/* 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;
-
-
-/****************************************************************************
-*  Toolbox Console Text Display Tool
-****************************************************************************/
-
-/* Toolbox Console Text Display Tool request message */
-typedef struct _MPI2_TOOLBOX_TEXT_DISPLAY_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                      Console;            /* 0x0C */
-       U8                      Flags;              /* 0x0D */
-       U16                     Reserved6;          /* 0x0E */
-       U8                      TextToDisplay[4];   /* 0x10 */
-} MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST,
-MPI2_POINTER PTR_MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST,
-Mpi2ToolboxTextDisplayRequest_t,
-MPI2_POINTER pMpi2ToolboxTextDisplayRequest_t;
-
-/* defines for the Console field */
-#define MPI2_TOOLBOX_CONSOLE_TYPE_MASK          (0xF0)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_DEFAULT       (0x00)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_UART          (0x10)
-#define MPI2_TOOLBOX_CONSOLE_TYPE_ETHERNET      (0x20)
-
-#define MPI2_TOOLBOX_CONSOLE_NUMBER_MASK        (0x0F)
-
-/* defines for the Flags field */
-#define MPI2_TOOLBOX_CONSOLE_FLAG_TIMESTAMP     (0x01)
-
-
-
-/*****************************************************************************
-*
-*       Diagnostic Buffer Messages
-*
-*****************************************************************************/
-
-
-/****************************************************************************
-*  Diagnostic Buffer Post request
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
-{
-    U8                      ExtendedType;               /* 0x00 */
-    U8                      BufferType;                 /* 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 */
-    U64                     BufferAddress;              /* 0x0C */
-    U32                     BufferLength;               /* 0x14 */
-    U32                     Reserved5;                  /* 0x18 */
-    U32                     Reserved6;                  /* 0x1C */
-    U32                     Flags;                      /* 0x20 */
-    U32                     ProductSpecific[23];        /* 0x24 */
-} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
-  Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t;
-
-/* values for the ExtendedType field */
-#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION         (0x02)
-
-/* values for the BufferType field */
-#define MPI2_DIAG_BUF_TYPE_TRACE                    (0x00)
-#define MPI2_DIAG_BUF_TYPE_SNAPSHOT                 (0x01)
-#define MPI2_DIAG_BUF_TYPE_EXTENDED                 (0x02)
-/* count of the number of buffer types */
-#define MPI2_DIAG_BUF_TYPE_COUNT                    (0x03)
-
-/* values for the Flags field */
-#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL          (0x00000002)
-#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE        (0x00000001)
-
-
-/****************************************************************************
-*  Diagnostic Buffer Post reply
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_BUFFER_POST_REPLY
-{
-    U8                      ExtendedType;               /* 0x00 */
-    U8                      BufferType;                 /* 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                     TransferLength;             /* 0x14 */
-} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY,
-  Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t;
-
-
-/****************************************************************************
-*  Diagnostic Release request
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_RELEASE_REQUEST
-{
-    U8                      Reserved1;                  /* 0x00 */
-    U8                      BufferType;                 /* 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 */
-} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST,
-  Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t;
-
-
-/****************************************************************************
-*  Diagnostic Buffer Post reply
-****************************************************************************/
-
-typedef struct _MPI2_DIAG_RELEASE_REPLY
-{
-    U8                      Reserved1;                  /* 0x00 */
-    U8                      BufferType;                 /* 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 */
-} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY,
-  Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t;
-
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
deleted file mode 100644 (file)
index 6b0dcdd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Copyright (c) 2000-2014 LSI Corporation.
- *
- *
- *           Name:  mpi2_type.h
- *          Title:  MPI basic type definitions
- *  Creation Date:  August 16, 2006
- *
- *    mpi2_type.h Version:  02.00.00
- *
- *  Version History
- *  ---------------
- *
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  --------------------------------------------------------------------------
- */
-
-#ifndef MPI2_TYPE_H
-#define MPI2_TYPE_H
-
-
-/*******************************************************************************
- * Define MPI2_POINTER if it hasn't already been defined. By default
- * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
- * a far pointer by defining MPI2_POINTER as "far *" before this header file is
- * included.
- */
-#ifndef MPI2_POINTER
-#define MPI2_POINTER     *
-#endif
-
-/* the basic types may have already been included by mpi_type.h */
-#ifndef MPI_TYPE_H
-/*****************************************************************************
-*
-*               Basic Types
-*
-*****************************************************************************/
-
-typedef u8 U8;
-typedef __le16 U16;
-typedef __le32 U32;
-typedef __le64 U64 __attribute__((aligned(4)));
-
-/*****************************************************************************
-*
-*               Pointer Types
-*
-*****************************************************************************/
-
-typedef U8      *PU8;
-typedef U16     *PU16;
-typedef U32     *PU32;
-typedef U64     *PU64;
-
-#endif
-
-#endif
-
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
deleted file mode 100644 (file)
index c167911..0000000
+++ /dev/null
@@ -1,4899 +0,0 @@
-/*
- * This is the Fusion MPT base driver providing common API layer interface
- * for access to MPT (Message Passing Technology) firmware.
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/sort.h>
-#include <linux/io.h>
-#include <linux/time.h>
-#include <linux/kthread.h>
-#include <linux/aer.h>
-
-#include "mpt2sas_base.h"
-
-static MPT_CALLBACK    mpt_callbacks[MPT_MAX_CALLBACKS];
-
-#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
-
-#define MAX_HBA_QUEUE_DEPTH    30000
-#define MAX_CHAIN_DEPTH                100000
-static int max_queue_depth = -1;
-module_param(max_queue_depth, int, 0);
-MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
-
-static int max_sgl_entries = -1;
-module_param(max_sgl_entries, int, 0);
-MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
-
-static int msix_disable = -1;
-module_param(msix_disable, int, 0);
-MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
-
-static int max_msix_vectors = -1;
-module_param(max_msix_vectors, int, 0);
-MODULE_PARM_DESC(max_msix_vectors, " max msix vectors ");
-
-static int mpt2sas_fwfault_debug;
-MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
-       "and halt firmware - (default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
-static int
-_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
-
-static int
-_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
-
-/**
- * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
- *
- */
-static int
-_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
-{
-       int ret = param_set_int(val, kp);
-       struct MPT2SAS_ADAPTER *ioc;
-
-       if (ret)
-               return ret;
-
-       /* global ioc spinlock to protect controller list on list operations */
-       printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug);
-       spin_lock(&gioc_lock);
-       list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
-               ioc->fwfault_debug = mpt2sas_fwfault_debug;
-       spin_unlock(&gioc_lock);
-       return 0;
-}
-
-module_param_call(mpt2sas_fwfault_debug, _scsih_set_fwfault_debug,
-    param_get_int, &mpt2sas_fwfault_debug, 0644);
-
-/**
- *  mpt2sas_remove_dead_ioc_func - kthread context to remove dead ioc
- * @arg: input argument, used to derive ioc
- *
- * Return 0 if controller is removed from pci subsystem.
- * Return -1 for other case.
- */
-static int mpt2sas_remove_dead_ioc_func(void *arg)
-{
-               struct MPT2SAS_ADAPTER *ioc = (struct MPT2SAS_ADAPTER *)arg;
-               struct pci_dev *pdev;
-
-               if ((ioc == NULL))
-                       return -1;
-
-               pdev = ioc->pdev;
-               if ((pdev == NULL))
-                       return -1;
-               pci_stop_and_remove_bus_device_locked(pdev);
-               return 0;
-}
-
-
-/**
- * _base_fault_reset_work - workq handling ioc fault conditions
- * @work: input argument, used to derive ioc
- * Context: sleep.
- *
- * Return nothing.
- */
-static void
-_base_fault_reset_work(struct work_struct *work)
-{
-       struct MPT2SAS_ADAPTER *ioc =
-           container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
-       unsigned long    flags;
-       u32 doorbell;
-       int rc;
-       struct task_struct *p;
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->shost_recovery || ioc->pci_error_recovery)
-               goto rearm_timer;
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-
-       doorbell = mpt2sas_base_get_iocstate(ioc, 0);
-       if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) {
-               printk(MPT2SAS_INFO_FMT "%s : SAS host is non-operational !!!!\n",
-                       ioc->name, __func__);
-
-               /* It may be possible that EEH recovery can resolve some of
-                * pci bus failure issues rather removing the dead ioc function
-                * by considering controller is in a non-operational state. So
-                * here priority is given to the EEH recovery. If it doesn't
-                * not resolve this issue, mpt2sas driver will consider this
-                * controller to non-operational state and remove the dead ioc
-                * function.
-                */
-               if (ioc->non_operational_loop++ < 5) {
-                       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock,
-                                                        flags);
-                       goto rearm_timer;
-               }
-
-               /*
-                * Call _scsih_flush_pending_cmds callback so that we flush all
-                * pending commands back to OS. This call is required to aovid
-                * deadlock at block layer. Dead IOC will fail to do diag reset,
-                * and this call is safe since dead ioc will never return any
-                * command back from HW.
-                */
-               ioc->schedule_dead_ioc_flush_running_cmds(ioc);
-               /*
-                * Set remove_host flag early since kernel thread will
-                * take some time to execute.
-                */
-               ioc->remove_host = 1;
-               /*Remove the Dead Host */
-               p = kthread_run(mpt2sas_remove_dead_ioc_func, ioc,
-                   "mpt2sas_dead_ioc_%d", ioc->id);
-               if (IS_ERR(p)) {
-                       printk(MPT2SAS_ERR_FMT
-                       "%s: Running mpt2sas_dead_ioc thread failed !!!!\n",
-                       ioc->name, __func__);
-               } else {
-                   printk(MPT2SAS_ERR_FMT
-                       "%s: Running mpt2sas_dead_ioc thread success !!!!\n",
-                       ioc->name, __func__);
-               }
-
-               return; /* don't rearm timer */
-       }
-
-       ioc->non_operational_loop = 0;
-
-       if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
-               rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-               printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
-                   __func__, (rc == 0) ? "success" : "failed");
-               doorbell = mpt2sas_base_get_iocstate(ioc, 0);
-               if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
-                       mpt2sas_base_fault_info(ioc, doorbell &
-                           MPI2_DOORBELL_DATA_MASK);
-       }
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- rearm_timer:
-       if (ioc->fault_reset_work_q)
-               queue_delayed_work(ioc->fault_reset_work_q,
-                   &ioc->fault_reset_work,
-                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-}
-
-/**
- * mpt2sas_base_start_watchdog - start the fault_reset_work_q
- * @ioc: per adapter object
- * Context: sleep.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
-{
-       unsigned long    flags;
-
-       if (ioc->fault_reset_work_q)
-               return;
-
-       /* initialize fault polling */
-       INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
-       snprintf(ioc->fault_reset_work_q_name,
-           sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
-       ioc->fault_reset_work_q =
-               create_singlethread_workqueue(ioc->fault_reset_work_q_name);
-       if (!ioc->fault_reset_work_q) {
-               printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
-                   ioc->name, __func__, __LINE__);
-                       return;
-       }
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->fault_reset_work_q)
-               queue_delayed_work(ioc->fault_reset_work_q,
-                   &ioc->fault_reset_work,
-                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-}
-
-/**
- * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
- * @ioc: per adapter object
- * Context: sleep.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
-{
-       unsigned long    flags;
-       struct workqueue_struct *wq;
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       wq = ioc->fault_reset_work_q;
-       ioc->fault_reset_work_q = NULL;
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-       if (wq) {
-               if (!cancel_delayed_work_sync(&ioc->fault_reset_work))
-                       flush_workqueue(wq);
-               destroy_workqueue(wq);
-       }
-}
-
-/**
- * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
- * @ioc: per adapter object
- * @fault_code: fault code
- *
- * Return nothing.
- */
-void
-mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
-{
-       printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
-           ioc->name, fault_code);
-}
-
-/**
- * mpt2sas_halt_firmware - halt's mpt controller firmware
- * @ioc: per adapter object
- *
- * For debugging timeout related issues.  Writing 0xCOFFEE00
- * to the doorbell register will halt controller firmware. With
- * the purpose to stop both driver and firmware, the enduser can
- * obtain a ring buffer from controller UART.
- */
-void
-mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc)
-{
-       u32 doorbell;
-
-       if (!ioc->fwfault_debug)
-               return;
-
-       dump_stack();
-
-       doorbell = readl(&ioc->chip->Doorbell);
-       if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
-               mpt2sas_base_fault_info(ioc , doorbell);
-       else {
-               writel(0xC0FFEE00, &ioc->chip->Doorbell);
-               printk(MPT2SAS_ERR_FMT "Firmware is halted due to command "
-                   "timeout\n", ioc->name);
-       }
-
-       panic("panic in %s\n", __func__);
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _base_sas_ioc_info - verbose translation of the ioc status
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @request_hdr: request mf
- *
- * Return nothing.
- */
-static void
-_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
-     MPI2RequestHeader_t *request_hdr)
-{
-       u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       char *desc = NULL;
-       u16 frame_sz;
-       char *func_str = NULL;
-
-       /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
-       if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
-           request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
-           request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
-               return;
-
-       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-               return;
-
-       switch (ioc_status) {
-
-/****************************************************************************
-*  Common IOCStatus values for all replies
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_INVALID_FUNCTION:
-               desc = "invalid function";
-               break;
-       case MPI2_IOCSTATUS_BUSY:
-               desc = "busy";
-               break;
-       case MPI2_IOCSTATUS_INVALID_SGL:
-               desc = "invalid sgl";
-               break;
-       case MPI2_IOCSTATUS_INTERNAL_ERROR:
-               desc = "internal error";
-               break;
-       case MPI2_IOCSTATUS_INVALID_VPID:
-               desc = "invalid vpid";
-               break;
-       case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
-               desc = "insufficient resources";
-               break;
-       case MPI2_IOCSTATUS_INVALID_FIELD:
-               desc = "invalid field";
-               break;
-       case MPI2_IOCSTATUS_INVALID_STATE:
-               desc = "invalid state";
-               break;
-       case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
-               desc = "op state not supported";
-               break;
-
-/****************************************************************************
-*  Config IOCStatus values
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
-               desc = "config invalid action";
-               break;
-       case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
-               desc = "config invalid type";
-               break;
-       case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
-               desc = "config invalid page";
-               break;
-       case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
-               desc = "config invalid data";
-               break;
-       case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
-               desc = "config no defaults";
-               break;
-       case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
-               desc = "config cant commit";
-               break;
-
-/****************************************************************************
-*  SCSI IO Reply
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
-       case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
-       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
-       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
-       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
-       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
-       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
-       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
-       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
-       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
-       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
-       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
-               break;
-
-/****************************************************************************
-*  For use by SCSI Initiator and SCSI Target end-to-end data protection
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
-               desc = "eedp guard error";
-               break;
-       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
-               desc = "eedp ref tag error";
-               break;
-       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
-               desc = "eedp app tag error";
-               break;
-
-/****************************************************************************
-*  SCSI Target values
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
-               desc = "target invalid io index";
-               break;
-       case MPI2_IOCSTATUS_TARGET_ABORTED:
-               desc = "target aborted";
-               break;
-       case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
-               desc = "target no conn retryable";
-               break;
-       case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
-               desc = "target no connection";
-               break;
-       case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
-               desc = "target xfer count mismatch";
-               break;
-       case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
-               desc = "target data offset error";
-               break;
-       case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
-               desc = "target too much write data";
-               break;
-       case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
-               desc = "target iu too short";
-               break;
-       case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
-               desc = "target ack nak timeout";
-               break;
-       case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
-               desc = "target nak received";
-               break;
-
-/****************************************************************************
-*  Serial Attached SCSI values
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
-               desc = "smp request failed";
-               break;
-       case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
-               desc = "smp data overrun";
-               break;
-
-/****************************************************************************
-*  Diagnostic Buffer Post / Diagnostic Release values
-****************************************************************************/
-
-       case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
-               desc = "diagnostic released";
-               break;
-       default:
-               break;
-       }
-
-       if (!desc)
-               return;
-
-       switch (request_hdr->Function) {
-       case MPI2_FUNCTION_CONFIG:
-               frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
-               func_str = "config_page";
-               break;
-       case MPI2_FUNCTION_SCSI_TASK_MGMT:
-               frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
-               func_str = "task_mgmt";
-               break;
-       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
-               frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
-               func_str = "sas_iounit_ctl";
-               break;
-       case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
-               frame_sz = sizeof(Mpi2SepRequest_t);
-               func_str = "enclosure";
-               break;
-       case MPI2_FUNCTION_IOC_INIT:
-               frame_sz = sizeof(Mpi2IOCInitRequest_t);
-               func_str = "ioc_init";
-               break;
-       case MPI2_FUNCTION_PORT_ENABLE:
-               frame_sz = sizeof(Mpi2PortEnableRequest_t);
-               func_str = "port_enable";
-               break;
-       case MPI2_FUNCTION_SMP_PASSTHROUGH:
-               frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
-               func_str = "smp_passthru";
-               break;
-       default:
-               frame_sz = 32;
-               func_str = "unknown";
-               break;
-       }
-
-       printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
-           " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
-
-       _debug_dump_mf(request_hdr, frame_sz/4);
-}
-
-/**
- * _base_display_event_data - verbose translation of firmware asyn events
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- *
- * Return nothing.
- */
-static void
-_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventNotificationReply_t *mpi_reply)
-{
-       char *desc = NULL;
-       u16 event;
-
-       if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
-               return;
-
-       event = le16_to_cpu(mpi_reply->Event);
-
-       switch (event) {
-       case MPI2_EVENT_LOG_DATA:
-               desc = "Log Data";
-               break;
-       case MPI2_EVENT_STATE_CHANGE:
-               desc = "Status Change";
-               break;
-       case MPI2_EVENT_HARD_RESET_RECEIVED:
-               desc = "Hard Reset Received";
-               break;
-       case MPI2_EVENT_EVENT_CHANGE:
-               desc = "Event Change";
-               break;
-       case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
-               desc = "Device Status Change";
-               break;
-       case MPI2_EVENT_IR_OPERATION_STATUS:
-               if (!ioc->hide_ir_msg)
-                       desc = "IR Operation Status";
-               break;
-       case MPI2_EVENT_SAS_DISCOVERY:
-       {
-               Mpi2EventDataSasDiscovery_t *event_data =
-                   (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData;
-               printk(MPT2SAS_INFO_FMT "Discovery: (%s)", ioc->name,
-                   (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
-                   "start" : "stop");
-               if (event_data->DiscoveryStatus)
-                       printk("discovery_status(0x%08x)",
-                           le32_to_cpu(event_data->DiscoveryStatus));
-               printk("\n");
-               return;
-       }
-       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
-               desc = "SAS Broadcast Primitive";
-               break;
-       case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
-               desc = "SAS Init Device Status Change";
-               break;
-       case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
-               desc = "SAS Init Table Overflow";
-               break;
-       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
-               desc = "SAS Topology Change List";
-               break;
-       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
-               desc = "SAS Enclosure Device Status Change";
-               break;
-       case MPI2_EVENT_IR_VOLUME:
-               if (!ioc->hide_ir_msg)
-                       desc = "IR Volume";
-               break;
-       case MPI2_EVENT_IR_PHYSICAL_DISK:
-               if (!ioc->hide_ir_msg)
-                       desc = "IR Physical Disk";
-               break;
-       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
-               if (!ioc->hide_ir_msg)
-                       desc = "IR Configuration Change List";
-               break;
-       case MPI2_EVENT_LOG_ENTRY_ADDED:
-               if (!ioc->hide_ir_msg)
-                       desc = "Log Entry Added";
-               break;
-       case MPI2_EVENT_TEMP_THRESHOLD:
-               desc = "Temperature Threshold";
-               break;
-       }
-
-       if (!desc)
-               return;
-
-       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
-}
-#endif
-
-/**
- * _base_sas_log_info - verbose translation of firmware log info
- * @ioc: per adapter object
- * @log_info: log info
- *
- * Return nothing.
- */
-static void
-_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
-{
-       union loginfo_type {
-               u32     loginfo;
-               struct {
-                       u32     subcode:16;
-                       u32     code:8;
-                       u32     originator:4;
-                       u32     bus_type:4;
-               } dw;
-       };
-       union loginfo_type sas_loginfo;
-       char *originator_str = NULL;
-
-       sas_loginfo.loginfo = log_info;
-       if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
-               return;
-
-       /* each nexus loss loginfo */
-       if (log_info == 0x31170000)
-               return;
-
-       /* eat the loginfos associated with task aborts */
-       if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info ==
-           0x31140000 || log_info == 0x31130000))
-               return;
-
-       switch (sas_loginfo.dw.originator) {
-       case 0:
-               originator_str = "IOP";
-               break;
-       case 1:
-               originator_str = "PL";
-               break;
-       case 2:
-               if (!ioc->hide_ir_msg)
-                       originator_str = "IR";
-               else
-                       originator_str = "WarpDrive";
-               break;
-       }
-
-       printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
-           "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
-            originator_str, sas_loginfo.dw.code,
-            sas_loginfo.dw.subcode);
-}
-
-/**
- * _base_display_reply_info -
- * @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)
- *
- * Return nothing.
- */
-static void
-_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
-    u32 reply)
-{
-       MPI2DefaultReply_t *mpi_reply;
-       u16 ioc_status;
-
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (unlikely(!mpi_reply)) {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                       ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
-           (ioc->logging_level & MPT_DEBUG_REPLY)) {
-               _base_sas_ioc_info(ioc , mpi_reply,
-                  mpt2sas_base_get_msg_frame(ioc, smid));
-       }
-#endif
-       if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
-               _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
-}
-
-/**
- * mpt2sas_base_done - base internal command 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)
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-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 1;
-
-       if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
-               return 1;
-
-       ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
-       if (mpi_reply) {
-               ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
-               memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
-       }
-       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: per adapter object
- * @msix_index: MSIX table index supplied by the OS
- * @reply: reply message frame(lower 32bit addr)
- *
- * Returns void.
- */
-static void
-_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
-{
-       Mpi2EventNotificationReply_t *mpi_reply;
-       Mpi2EventAckRequest_t *ack_request;
-       u16 smid;
-
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (!mpi_reply)
-               return;
-       if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
-               return;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       _base_display_event_data(ioc, mpi_reply);
-#endif
-       if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
-               goto out;
-       smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               goto out;
-       }
-
-       ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
-       ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
-       ack_request->Event = mpi_reply->Event;
-       ack_request->EventContext = mpi_reply->EventContext;
-       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, msix_index, reply);
-
-       /* ctl callback handler */
-       mpt2sas_ctl_event_callback(ioc, msix_index, reply);
-
-       return;
-}
-
-/**
- * _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;
-
-       if (smid < ioc->hi_priority_smid) {
-               i = smid - 1;
-               cb_idx = ioc->scsi_lookup[i].cb_idx;
-       } else if (smid < ioc->internal_smid) {
-               i = smid - ioc->hi_priority_smid;
-               cb_idx = ioc->hpr_lookup[i].cb_idx;
-       } else if (smid <= ioc->hba_queue_depth) {
-               i = smid - ioc->internal_smid;
-               cb_idx = ioc->internal_lookup[i].cb_idx;
-       } else
-               cb_idx = 0xFF;
-       return cb_idx;
-}
-
-/**
- * _base_mask_interrupts - disable interrupts
- * @ioc: per adapter object
- *
- * Disabling ResetIRQ, Reply and Doorbell Interrupts
- *
- * Return nothing.
- */
-static void
-_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
-{
-       u32 him_register;
-
-       ioc->mask_interrupts = 1;
-       him_register = readl(&ioc->chip->HostInterruptMask);
-       him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
-       writel(him_register, &ioc->chip->HostInterruptMask);
-       readl(&ioc->chip->HostInterruptMask);
-}
-
-/**
- * _base_unmask_interrupts - enable interrupts
- * @ioc: per adapter object
- *
- * Enabling only Reply Interrupts
- *
- * Return nothing.
- */
-static void
-_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
-{
-       u32 him_register;
-
-       him_register = readl(&ioc->chip->HostInterruptMask);
-       him_register &= ~MPI2_HIM_RIM;
-       writel(him_register, &ioc->chip->HostInterruptMask);
-       ioc->mask_interrupts = 0;
-}
-
-union reply_descriptor {
-       u64 word;
-       struct {
-               u32 low;
-               u32 high;
-       } u;
-};
-
-/**
- * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
- * @irq: irq number (not used)
- * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
- * @r: pt_regs pointer (not used)
- *
- * Return IRQ_HANDLE if processed, else IRQ_NONE.
- */
-static irqreturn_t
-_base_interrupt(int irq, void *bus_id)
-{
-       struct adapter_reply_queue *reply_q = bus_id;
-       union reply_descriptor rd;
-       u32 completed_cmds;
-       u8 request_desript_type;
-       u16 smid;
-       u8 cb_idx;
-       u32 reply;
-       u8 msix_index = reply_q->msix_index;
-       struct MPT2SAS_ADAPTER *ioc = reply_q->ioc;
-       Mpi2ReplyDescriptorsUnion_t *rpf;
-       u8 rc;
-
-       if (ioc->mask_interrupts)
-               return IRQ_NONE;
-
-       if (!atomic_add_unless(&reply_q->busy, 1, 1))
-               return IRQ_NONE;
-
-       rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index];
-       request_desript_type = rpf->Default.ReplyFlags
-            & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-       if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) {
-               atomic_dec(&reply_q->busy);
-               return IRQ_NONE;
-       }
-
-       completed_cmds = 0;
-       cb_idx = 0xFF;
-       do {
-               rd.word = le64_to_cpu(rpf->Words);
-               if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
-                       goto out;
-               reply = 0;
-               smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1);
-               if (request_desript_type ==
-                   MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
-                       reply = le32_to_cpu
-                               (rpf->AddressReply.ReplyFrameAddress);
-                       if (reply > ioc->reply_dma_max_address ||
-                           reply < ioc->reply_dma_min_address)
-                               reply = 0;
-               } else if (request_desript_type ==
-                   MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
-                       goto next;
-               else if (request_desript_type ==
-                   MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
-                       goto next;
-               if (smid) {
-                       cb_idx = _base_get_cb_idx(ioc, smid);
-               if ((likely(cb_idx < MPT_MAX_CALLBACKS))
-                           && (likely(mpt_callbacks[cb_idx] != NULL))) {
-                               rc = mpt_callbacks[cb_idx](ioc, smid,
-                                   msix_index, reply);
-                       if (reply)
-                               _base_display_reply_info(ioc, smid,
-                                   msix_index, reply);
-                       if (rc)
-                               mpt2sas_base_free_smid(ioc, smid);
-                       }
-               }
-               if (!smid)
-                       _base_async_event(ioc, msix_index, reply);
-
-               /* reply free queue handling */
-               if (reply) {
-                       ioc->reply_free_host_index =
-                           (ioc->reply_free_host_index ==
-                           (ioc->reply_free_queue_depth - 1)) ?
-                           0 : ioc->reply_free_host_index + 1;
-                       ioc->reply_free[ioc->reply_free_host_index] =
-                           cpu_to_le32(reply);
-                       wmb();
-                       writel(ioc->reply_free_host_index,
-                           &ioc->chip->ReplyFreeHostIndex);
-               }
-
- next:
-
-               rpf->Words = cpu_to_le64(ULLONG_MAX);
-               reply_q->reply_post_host_index =
-                   (reply_q->reply_post_host_index ==
-                   (ioc->reply_post_queue_depth - 1)) ? 0 :
-                   reply_q->reply_post_host_index + 1;
-               request_desript_type =
-                   reply_q->reply_post_free[reply_q->reply_post_host_index].
-                   Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
-               completed_cmds++;
-               if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
-                       goto out;
-               if (!reply_q->reply_post_host_index)
-                       rpf = reply_q->reply_post_free;
-               else
-                       rpf++;
-       } while (1);
-
- out:
-
-       if (!completed_cmds) {
-               atomic_dec(&reply_q->busy);
-               return IRQ_NONE;
-       }
-       wmb();
-       if (ioc->is_warpdrive) {
-               writel(reply_q->reply_post_host_index,
-               ioc->reply_post_host_index[msix_index]);
-               atomic_dec(&reply_q->busy);
-               return IRQ_HANDLED;
-       }
-       writel(reply_q->reply_post_host_index | (msix_index <<
-           MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex);
-       atomic_dec(&reply_q->busy);
-       return IRQ_HANDLED;
-}
-
-/**
- * _base_is_controller_msix_enabled - is controller support muli-reply queues
- * @ioc: per adapter object
- *
- */
-static inline int
-_base_is_controller_msix_enabled(struct MPT2SAS_ADAPTER *ioc)
-{
-       return (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable;
-}
-
-/**
- * mpt2sas_base_flush_reply_queues - flushing the MSIX reply queues
- * @ioc: per adapter object
- * Context: ISR conext
- *
- * Called when a Task Management request has completed. We want
- * to flush the other reply queues so all the outstanding IO has been
- * completed back to OS before we process the TM completetion.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct adapter_reply_queue *reply_q;
-
-       /* If MSIX capability is turned off
-        * then multi-queues are not enabled
-        */
-       if (!_base_is_controller_msix_enabled(ioc))
-               return;
-
-       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-               if (ioc->shost_recovery)
-                       return;
-               /* TMs are on msix_index == 0 */
-               if (reply_q->msix_index == 0)
-                       continue;
-               _base_interrupt(reply_q->vector, (void *)reply_q);
-       }
-}
-
-/**
- * mpt2sas_base_release_callback_handler - clear interrupt callback handler
- * @cb_idx: callback index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_release_callback_handler(u8 cb_idx)
-{
-       mpt_callbacks[cb_idx] = NULL;
-}
-
-/**
- * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
- * @cb_func: callback function
- *
- * Returns cb_func.
- */
-u8
-mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
-{
-       u8 cb_idx;
-
-       for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
-               if (mpt_callbacks[cb_idx] == NULL)
-                       break;
-
-       mpt_callbacks[cb_idx] = cb_func;
-       return cb_idx;
-}
-
-/**
- * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
- *
- * Return nothing.
- */
-void
-mpt2sas_base_initialize_callback_handler(void)
-{
-       u8 cb_idx;
-
-       for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
-               mpt2sas_base_release_callback_handler(cb_idx);
-}
-
-/**
- * mpt2sas_base_build_zero_len_sge - build zero length sg entry
- * @ioc: per adapter object
- * @paddr: virtual address for SGE
- *
- * Create a zero length scatter gather entry to insure the IOCs hardware has
- * something to use if the target device goes brain dead and tries
- * to send data even when none is asked for.
- *
- * Return nothing.
- */
-void
-mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
-{
-       u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
-           MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
-           MPI2_SGE_FLAGS_SHIFT);
-       ioc->base_add_sg_single(paddr, flags_length, -1);
-}
-
-/**
- * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
- * @paddr: virtual address for SGE
- * @flags_length: SGE flags and data transfer length
- * @dma_addr: Physical address
- *
- * Return nothing.
- */
-static void
-_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
-{
-       Mpi2SGESimple32_t *sgel = paddr;
-
-       flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
-           MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
-       sgel->FlagsLength = cpu_to_le32(flags_length);
-       sgel->Address = cpu_to_le32(dma_addr);
-}
-
-
-/**
- * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
- * @paddr: virtual address for SGE
- * @flags_length: SGE flags and data transfer length
- * @dma_addr: Physical address
- *
- * Return nothing.
- */
-static void
-_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
-{
-       Mpi2SGESimple64_t *sgel = paddr;
-
-       flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
-           MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
-       sgel->FlagsLength = cpu_to_le32(flags_length);
-       sgel->Address = cpu_to_le64(dma_addr);
-}
-
-#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
-
-/**
- * _base_config_dma_addressing - set dma addressing
- * @ioc: per adapter object
- * @pdev: PCI device struct
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
-{
-       struct sysinfo s;
-       u64 consistent_dma_mask;
-
-       if (ioc->dma_mask)
-               consistent_dma_mask = DMA_BIT_MASK(64);
-       else
-               consistent_dma_mask = DMA_BIT_MASK(32);
-
-       if (sizeof(dma_addr_t) > 4) {
-               const uint64_t required_mask =
-                   dma_get_required_mask(&pdev->dev);
-               if ((required_mask > DMA_BIT_MASK(32)) &&
-                   !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
-                   !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) {
-                       ioc->base_add_sg_single = &_base_add_sg_single_64;
-                       ioc->sge_size = sizeof(Mpi2SGESimple64_t);
-                       ioc->dma_mask = 64;
-                       goto out;
-               }
-       }
-
-       if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
-           && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               ioc->base_add_sg_single = &_base_add_sg_single_32;
-               ioc->sge_size = sizeof(Mpi2SGESimple32_t);
-               ioc->dma_mask = 32;
-       } else
-               return -ENODEV;
-
- out:
-       si_meminfo(&s);
-       printk(MPT2SAS_INFO_FMT
-           "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
-           ioc->name, ioc->dma_mask, convert_to_kb(s.totalram));
-
-       return 0;
-}
-
-static int
-_base_change_consistent_dma_mask(struct MPT2SAS_ADAPTER *ioc,
-                                 struct pci_dev *pdev)
-{
-       if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
-               if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
-                       return -ENODEV;
-       }
-       return 0;
-}
-/**
- * _base_check_enable_msix - checks MSIX capabable.
- * @ioc: per adapter object
- *
- * Check to see if card is capable of MSIX, and set number
- * of available msix vectors
- */
-static int
-_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
-       int base;
-       u16 message_control;
-
-
-       /* Check whether controller SAS2008 B0 controller,
-          if it is SAS2008 B0 controller use IO-APIC instead of MSIX */
-       if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
-           ioc->pdev->revision == 0x01) {
-               return -EINVAL;
-       }
-
-       base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
-       if (!base) {
-               dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
-                   "supported\n", ioc->name));
-               return -EINVAL;
-       }
-
-       /* get msix vector count */
-       /* NUMA_IO not supported for older controllers */
-       if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
-           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
-               ioc->msix_vector_count = 1;
-       else {
-               pci_read_config_word(ioc->pdev, base + 2, &message_control);
-               ioc->msix_vector_count = (message_control & 0x3FF) + 1;
-       }
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
-           "vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
-
-       return 0;
-}
-
-/**
- * _base_free_irq - free irq
- * @ioc: per adapter object
- *
- * Freeing respective reply_queue from the list.
- */
-static void
-_base_free_irq(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct adapter_reply_queue *reply_q, *next;
-
-       if (list_empty(&ioc->reply_queue_list))
-               return;
-
-       list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
-               list_del(&reply_q->list);
-               irq_set_affinity_hint(reply_q->vector, NULL);
-               free_cpumask_var(reply_q->affinity_hint);
-               synchronize_irq(reply_q->vector);
-               free_irq(reply_q->vector, reply_q);
-               kfree(reply_q);
-       }
-}
-
-/**
- * _base_request_irq - request irq
- * @ioc: per adapter object
- * @index: msix index into vector table
- * @vector: irq vector
- *
- * Inserting respective reply_queue into the list.
- */
-static int
-_base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector)
-{
-       struct adapter_reply_queue *reply_q;
-       int r;
-
-       reply_q =  kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL);
-       if (!reply_q) {
-               printk(MPT2SAS_ERR_FMT "unable to allocate memory %d!\n",
-                   ioc->name, (int)sizeof(struct adapter_reply_queue));
-               return -ENOMEM;
-       }
-       reply_q->ioc = ioc;
-       reply_q->msix_index = index;
-       reply_q->vector = vector;
-
-       if (!alloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL))
-               return -ENOMEM;
-       cpumask_clear(reply_q->affinity_hint);
-
-       atomic_set(&reply_q->busy, 0);
-       if (ioc->msix_enable)
-               snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
-                   MPT2SAS_DRIVER_NAME, ioc->id, index);
-       else
-               snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
-                   MPT2SAS_DRIVER_NAME, ioc->id);
-       r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
-           reply_q);
-       if (r) {
-               printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
-                   reply_q->name, vector);
-               kfree(reply_q);
-               return -EBUSY;
-       }
-
-       INIT_LIST_HEAD(&reply_q->list);
-       list_add_tail(&reply_q->list, &ioc->reply_queue_list);
-       return 0;
-}
-
-/**
- * _base_assign_reply_queues - assigning msix index for each cpu
- * @ioc: per adapter object
- *
- * The enduser would need to set the affinity via /proc/irq/#/smp_affinity
- *
- * It would nice if we could call irq_set_affinity, however it is not
- * an exported symbol
- */
-static void
-_base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc)
-{
-       unsigned int cpu, nr_cpus, nr_msix, index = 0;
-       struct adapter_reply_queue *reply_q;
-
-       if (!_base_is_controller_msix_enabled(ioc))
-               return;
-
-       memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz);
-
-       nr_cpus = num_online_cpus();
-       nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count,
-                                              ioc->facts.MaxMSIxVectors);
-       if (!nr_msix)
-               return;
-
-       cpu = cpumask_first(cpu_online_mask);
-
-       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-
-               unsigned int i, group = nr_cpus / nr_msix;
-
-               if (cpu >= nr_cpus)
-                       break;
-
-               if (index < nr_cpus % nr_msix)
-                       group++;
-
-               for (i = 0 ; i < group ; i++) {
-                       ioc->cpu_msix_table[cpu] = index;
-                       cpumask_or(reply_q->affinity_hint,
-                                  reply_q->affinity_hint, get_cpu_mask(cpu));
-                       cpu = cpumask_next(cpu, cpu_online_mask);
-               }
-
-               if (irq_set_affinity_hint(reply_q->vector,
-                                          reply_q->affinity_hint))
-                       dinitprintk(ioc, pr_info(MPT2SAS_FMT
-                           "error setting affinity hint for irq vector %d\n",
-                           ioc->name, reply_q->vector));
-               index++;
-       }
-}
-
-/**
- * _base_disable_msix - disables msix
- * @ioc: per adapter object
- *
- */
-static void
-_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
-       if (ioc->msix_enable) {
-               pci_disable_msix(ioc->pdev);
-               ioc->msix_enable = 0;
-       }
-}
-
-/**
- * _base_enable_msix - enables msix, failback to io_apic
- * @ioc: per adapter object
- *
- */
-static int
-_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct msix_entry *entries, *a;
-       int r;
-       int i;
-       u8 try_msix = 0;
-
-       if (msix_disable == -1 || msix_disable == 0)
-               try_msix = 1;
-
-       if (!try_msix)
-               goto try_ioapic;
-
-       if (_base_check_enable_msix(ioc) != 0)
-               goto try_ioapic;
-
-       ioc->reply_queue_count = min_t(int, ioc->cpu_count,
-           ioc->msix_vector_count);
-
-       if (!ioc->rdpq_array_enable && max_msix_vectors == -1)
-               max_msix_vectors = 8;
-
-       if (max_msix_vectors > 0) {
-               ioc->reply_queue_count = min_t(int, max_msix_vectors,
-                   ioc->reply_queue_count);
-               ioc->msix_vector_count = ioc->reply_queue_count;
-       } else if (max_msix_vectors == 0)
-               goto try_ioapic;
-
-       printk(MPT2SAS_INFO_FMT
-       "MSI-X vectors supported: %d, no of cores: %d, max_msix_vectors: %d\n",
-        ioc->name, ioc->msix_vector_count, ioc->cpu_count, max_msix_vectors);
-
-       entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
-           GFP_KERNEL);
-       if (!entries) {
-               dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "kcalloc "
-                   "failed @ at %s:%d/%s() !!!\n", ioc->name, __FILE__,
-                   __LINE__, __func__));
-               goto try_ioapic;
-       }
-
-       for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++)
-               a->entry = i;
-
-       r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count);
-       if (r) {
-               dfailprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "pci_enable_msix_exact failed (r=%d) !!!\n", ioc->name, r));
-               kfree(entries);
-               goto try_ioapic;
-       }
-
-       ioc->msix_enable = 1;
-       for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) {
-               r = _base_request_irq(ioc, i, a->vector);
-               if (r) {
-                       _base_free_irq(ioc);
-                       _base_disable_msix(ioc);
-                       kfree(entries);
-                       goto try_ioapic;
-               }
-       }
-
-       kfree(entries);
-       return 0;
-
-/* failback to io_apic interrupt routing */
- try_ioapic:
-
-       ioc->reply_queue_count = 1;
-       r = _base_request_irq(ioc, 0, ioc->pdev->irq);
-
-       return r;
-}
-
-/**
- * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct pci_dev *pdev = ioc->pdev;
-       u32 memap_sz;
-       u32 pio_sz;
-       int i, r = 0;
-       u64 pio_chip = 0;
-       u64 chip_phys = 0;
-       struct adapter_reply_queue *reply_q;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n",
-           ioc->name, __func__));
-
-       ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
-       if (pci_enable_device_mem(pdev)) {
-               printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
-                   "failed\n", ioc->name);
-               ioc->bars = 0;
-               return -ENODEV;
-       }
-
-
-       if (pci_request_selected_regions(pdev, ioc->bars,
-           MPT2SAS_DRIVER_NAME)) {
-               printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
-                   "failed\n", ioc->name);
-               ioc->bars = 0;
-               r = -ENODEV;
-               goto out_fail;
-       }
-
-       /* AER (Advanced Error Reporting) hooks */
-       pci_enable_pcie_error_reporting(pdev);
-
-       pci_set_master(pdev);
-
-       if (_base_config_dma_addressing(ioc, pdev) != 0) {
-               printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
-                   ioc->name, pci_name(pdev));
-               r = -ENODEV;
-               goto out_fail;
-       }
-
-       for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) &&
-            (!memap_sz || !pio_sz); i++) {
-               if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-                       if (pio_sz)
-                               continue;
-                       pio_chip = (u64)pci_resource_start(pdev, i);
-                       pio_sz = pci_resource_len(pdev, i);
-               } else {
-                       if (memap_sz)
-                               continue;
-                       /* verify memory resource is valid before using */
-                       if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
-                               ioc->chip_phys = pci_resource_start(pdev, i);
-                               chip_phys = (u64)ioc->chip_phys;
-                               memap_sz = pci_resource_len(pdev, i);
-                               ioc->chip = ioremap(ioc->chip_phys, memap_sz);
-                       }
-               }
-       }
-
-       if (ioc->chip == NULL) {
-               printk(MPT2SAS_ERR_FMT "unable to map adapter memory! "
-                      "or resource not found\n", ioc->name);
-               r = -EINVAL;
-               goto out_fail;
-       }
-
-       _base_mask_interrupts(ioc);
-
-       r = _base_get_ioc_facts(ioc, CAN_SLEEP);
-       if (r)
-               goto out_fail;
-
-       if (!ioc->rdpq_array_enable_assigned) {
-               ioc->rdpq_array_enable = ioc->rdpq_array_capable;
-               ioc->rdpq_array_enable_assigned = 1;
-       }
-
-       r = _base_enable_msix(ioc);
-       if (r)
-               goto out_fail;
-
-       list_for_each_entry(reply_q, &ioc->reply_queue_list, list)
-               printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
-                   reply_q->name,  ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
-                   "IO-APIC enabled"), reply_q->vector);
-
-       printk(MPT2SAS_INFO_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n",
-           ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz);
-       printk(MPT2SAS_INFO_FMT "ioport(0x%016llx), size(%d)\n",
-           ioc->name, (unsigned long long)pio_chip, pio_sz);
-
-       /* Save PCI configuration state for recovery from PCI AER/EEH errors */
-       pci_save_state(pdev);
-
-       return 0;
-
- out_fail:
-       if (ioc->chip_phys)
-               iounmap(ioc->chip);
-       ioc->chip_phys = 0;
-       pci_release_selected_regions(ioc->pdev, ioc->bars);
-       pci_disable_pcie_error_reporting(pdev);
-       pci_disable_device(pdev);
-       return r;
-}
-
-/**
- * mpt2sas_base_get_msg_frame - obtain request mf pointer
- * @ioc: per adapter object
- * @smid: system request message index(smid zero is invalid)
- *
- * Returns virt pointer to message frame.
- */
-void *
-mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return (void *)(ioc->request + (smid * ioc->request_sz));
-}
-
-/**
- * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns virt pointer to sense buffer.
- */
-void *
-mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
-}
-
-/**
- * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns phys pointer to the low 32bit address of the sense buffer.
- */
-__le32
-mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return cpu_to_le32(ioc->sense_dma +
-                       ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
-}
-
-/**
- * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
- * @ioc: per adapter object
- * @phys_addr: lower 32 physical addr of the reply
- *
- * Converts 32bit lower physical addr into a virt address.
- */
-void *
-mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
-{
-       if (!phys_addr)
-               return NULL;
-       return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
-}
-
-/**
- * mpt2sas_base_get_smid - obtain a free smid from internal queue
- * @ioc: per adapter object
- * @cb_idx: callback index
- *
- * Returns smid (zero is invalid)
- */
-u16
-mpt2sas_base_get_smid(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->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 scsiio_tracker *request;
-       u16 smid;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       if (list_empty(&ioc->free_list)) {
-               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-               printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
-                   ioc->name, __func__);
-               return 0;
-       }
-
-       request = list_entry(ioc->free_list.next,
-           struct scsiio_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);
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return smid;
-}
-
-
-/**
- * mpt2sas_base_free_smid - put smid back on free_list
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       unsigned long flags;
-       int i;
-       struct chain_tracker *chain_req, *next;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       if (smid < ioc->hi_priority_smid) {
-               /* scsiio queue */
-               i = smid - 1;
-               if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
-                       list_for_each_entry_safe(chain_req, next,
-                           &ioc->scsi_lookup[i].chain_list, tracker_list) {
-                               list_del_init(&chain_req->tracker_list);
-                               list_add(&chain_req->tracker_list,
-                                   &ioc->free_chain_list);
-                       }
-               }
-               ioc->scsi_lookup[i].cb_idx = 0xFF;
-               ioc->scsi_lookup[i].scmd = NULL;
-               ioc->scsi_lookup[i].direct_io = 0;
-               list_add(&ioc->scsi_lookup[i].tracker_list,
-                   &ioc->free_list);
-               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
-               /*
-                * See _wait_for_commands_to_complete() call with regards
-                * to this code.
-                */
-               if (ioc->shost_recovery && ioc->pending_io_count) {
-                       if (ioc->pending_io_count == 1)
-                               wake_up(&ioc->reset_wq);
-                       ioc->pending_io_count--;
-               }
-               return;
-       } else if (smid < ioc->internal_smid) {
-               /* hi-priority */
-               i = smid - ioc->hi_priority_smid;
-               ioc->hpr_lookup[i].cb_idx = 0xFF;
-               list_add(&ioc->hpr_lookup[i].tracker_list,
-                   &ioc->hpr_free_list);
-       } else if (smid <= ioc->hba_queue_depth) {
-               /* internal queue */
-               i = smid - ioc->internal_smid;
-               ioc->internal_lookup[i].cb_idx = 0xFF;
-               list_add(&ioc->internal_lookup[i].tracker_list,
-                   &ioc->internal_free_list);
-       }
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-}
-
-/**
- * _base_writeq - 64 bit write to MMIO
- * @ioc: per adapter object
- * @b: data payload
- * @addr: address in MMIO space
- * @writeq_lock: spin lock
- *
- * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
- * care of 32 bit environment where its not quarenteed to send the entire word
- * in one transfer.
- */
-#ifndef writeq
-static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
-    spinlock_t *writeq_lock)
-{
-       unsigned long flags;
-       __u64 data_out = cpu_to_le64(b);
-
-       spin_lock_irqsave(writeq_lock, flags);
-       writel((u32)(data_out), addr);
-       writel((u32)(data_out >> 32), (addr + 4));
-       spin_unlock_irqrestore(writeq_lock, flags);
-}
-#else
-static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
-    spinlock_t *writeq_lock)
-{
-       writeq(cpu_to_le64(b), addr);
-}
-#endif
-
-static inline u8
-_base_get_msix_index(struct MPT2SAS_ADAPTER *ioc)
-{
-       return ioc->cpu_msix_table[raw_smp_processor_id()];
-}
-
-/**
- * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- * @handle: device handle
- *
- * Return nothing.
- */
-void
-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.MSIxIndex =  _base_get_msix_index(ioc);
-       descriptor.SCSIIO.SMID = cpu_to_le16(smid);
-       descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
-       descriptor.SCSIIO.LMID = 0;
-       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
-           &ioc->scsi_lookup_lock);
-}
-
-
-/**
- * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-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.MSIxIndex =  0;
-       descriptor.HighPriority.SMID = cpu_to_le16(smid);
-       descriptor.HighPriority.LMID = 0;
-       descriptor.HighPriority.Reserved1 = 0;
-       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
-           &ioc->scsi_lookup_lock);
-}
-
-/**
- * mpt2sas_base_put_smid_default - Default, primarily used for config pages
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Return nothing.
- */
-void
-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.MSIxIndex =  _base_get_msix_index(ioc);
-       descriptor.Default.SMID = cpu_to_le16(smid);
-       descriptor.Default.LMID = 0;
-       descriptor.Default.DescriptorTypeDependent = 0;
-       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
-           &ioc->scsi_lookup_lock);
-}
-
-/**
- * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
- * @ioc: per adapter object
- * @smid: system request message index
- * @io_index: value used to track the IO
- *
- * Return nothing.
- */
-void
-mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    u16 io_index)
-{
-       Mpi2RequestDescriptorUnion_t descriptor;
-       u64 *request = (u64 *)&descriptor;
-
-       descriptor.SCSITarget.RequestFlags =
-           MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
-       descriptor.SCSITarget.MSIxIndex =  _base_get_msix_index(ioc);
-       descriptor.SCSITarget.SMID = cpu_to_le16(smid);
-       descriptor.SCSITarget.LMID = 0;
-       descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
-       _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
-           &ioc->scsi_lookup_lock);
-}
-
-/**
- * _base_display_dell_branding - Disply branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
-{
-       char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
-
-       if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
-               return;
-
-       memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
-       switch (ioc->pdev->subsystem_device) {
-       case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
-               strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
-               strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
-               strncpy(dell_branding,
-                   MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
-               strncpy(dell_branding,
-                   MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
-               strncpy(dell_branding,
-                   MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_PERC_H200_SSDID:
-               strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       case MPT2SAS_DELL_6GBPS_SAS_SSDID:
-               strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
-                   MPT2SAS_DELL_BRANDING_SIZE - 1);
-               break;
-       default:
-               sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
-               break;
-       }
-
-       printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
-           " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
-           ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
-           ioc->pdev->subsystem_device);
-}
-
-/**
- * _base_display_intel_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
-{
-       if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
-               return;
-
-       switch (ioc->pdev->device) {
-       case MPI2_MFGPAGE_DEVID_SAS2008:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT2SAS_INTEL_RMS2LL080_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS2LL080_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS2LL040_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS2LL040_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_SSD910_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_SSD910_BRANDING);
-                       break;
-               default:
-                       break;
-               }
-       case MPI2_MFGPAGE_DEVID_SAS2308_2:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT2SAS_INTEL_RS25GB008_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RS25GB008_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25JB080_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25JB080_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25JB040_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25JB040_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25KB080_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25KB080_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25KB040_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25KB040_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25LB040_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25LB040_BRANDING);
-                       break;
-               case MPT2SAS_INTEL_RMS25LB080_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_INTEL_RMS25LB080_BRANDING);
-                       break;
-               default:
-                       break;
-               }
-       default:
-               break;
-       }
-}
-
-/**
- * _base_display_hp_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
-{
-       if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
-               return;
-
-       switch (ioc->pdev->device) {
-       case MPI2_MFGPAGE_DEVID_SAS2004:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
-                       break;
-               default:
-                       break;
-               }
-       case MPI2_MFGPAGE_DEVID_SAS2308_2:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT2SAS_HP_2_4_INTERNAL_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_HP_2_4_INTERNAL_BRANDING);
-                       break;
-               case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
-                       break;
-               case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
-                       break;
-               case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
-                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-                           MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
-                       break;
-               default:
-                       break;
-               }
-       default:
-               break;
-       }
-}
-
-/**
- * _base_display_ioc_capabilities - Disply IOC's capabilities.
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
-{
-       int i = 0;
-       char desc[16];
-       u32 iounit_pg1_flags;
-       u32 bios_version;
-
-       bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
-       strncpy(desc, ioc->manu_pg0.ChipName, 16);
-       printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
-          "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
-           ioc->name, desc,
-          (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
-          (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
-          (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
-          ioc->facts.FWVersion.Word & 0x000000FF,
-          ioc->pdev->revision,
-          (bios_version & 0xFF000000) >> 24,
-          (bios_version & 0x00FF0000) >> 16,
-          (bios_version & 0x0000FF00) >> 8,
-           bios_version & 0x000000FF);
-
-       _base_display_dell_branding(ioc);
-       _base_display_intel_branding(ioc);
-       _base_display_hp_branding(ioc);
-
-       printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
-
-       if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
-               printk("Initiator");
-               i++;
-       }
-
-       if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
-               printk("%sTarget", i ? "," : "");
-               i++;
-       }
-
-       i = 0;
-       printk("), ");
-       printk("Capabilities=(");
-
-       if (!ioc->hide_ir_msg) {
-               if (ioc->facts.IOCCapabilities &
-                   MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
-                       printk("Raid");
-                       i++;
-               }
-       }
-
-       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
-               printk("%sTLR", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
-               printk("%sMulticast", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
-               printk("%sBIDI Target", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
-               printk("%sEEDP", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
-               printk("%sSnapshot Buffer", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
-               printk("%sDiag Trace Buffer", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
-               printk(KERN_INFO "%sDiag Extended Buffer", i ? "," : "");
-               i++;
-       }
-
-       if (ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
-               printk("%sTask Set Full", i ? "," : "");
-               i++;
-       }
-
-       iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
-       if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
-               printk("%sNCQ", i ? "," : "");
-               i++;
-       }
-
-       printk(")\n");
-}
-
-/**
- * mpt2sas_base_update_missing_delay - change the missing delay timers
- * @ioc: per adapter object
- * @device_missing_delay: amount of time till device is reported missing
- * @io_missing_delay: interval IO is returned when there is a missing device
- *
- * Return nothing.
- *
- * Passed on the command line, this function will modify the device missing
- * delay, as well as the io missing delay. This should be called at driver
- * load time.
- */
-void
-mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
-       u16 device_missing_delay, u8 io_missing_delay)
-{
-       u16 dmd, dmd_new, dmd_orignal;
-       u8 io_missing_delay_original;
-       u16 sz;
-       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
-       Mpi2ConfigReply_t mpi_reply;
-       u8 num_phys = 0;
-       u16 ioc_status;
-
-       mpt2sas_config_get_number_hba_phys(ioc, &num_phys);
-       if (!num_phys)
-               return;
-
-       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys *
-           sizeof(Mpi2SasIOUnit1PhyData_t));
-       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg1) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
-           sas_iounit_pg1, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-
-       /* device missing delay */
-       dmd = sas_iounit_pg1->ReportDeviceMissingDelay;
-       if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
-               dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
-       else
-               dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
-       dmd_orignal = dmd;
-       if (device_missing_delay > 0x7F) {
-               dmd = (device_missing_delay > 0x7F0) ? 0x7F0 :
-                   device_missing_delay;
-               dmd = dmd / 16;
-               dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16;
-       } else
-               dmd = device_missing_delay;
-       sas_iounit_pg1->ReportDeviceMissingDelay = dmd;
-
-       /* io missing delay */
-       io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay;
-       sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay;
-
-       if (!mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
-           sz)) {
-               if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
-                       dmd_new = (dmd &
-                           MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
-               else
-                       dmd_new =
-                   dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
-               printk(MPT2SAS_INFO_FMT "device_missing_delay: old(%d), "
-                   "new(%d)\n", ioc->name, dmd_orignal, dmd_new);
-               printk(MPT2SAS_INFO_FMT "ioc_missing_delay: old(%d), "
-                   "new(%d)\n", ioc->name, io_missing_delay_original,
-                   io_missing_delay);
-               ioc->device_missing_delay = dmd_new;
-               ioc->io_missing_delay = io_missing_delay;
-       }
-
-out:
-       kfree(sas_iounit_pg1);
-}
-
-/**
- * _base_static_config_pages - static start of day config pages
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2ConfigReply_t mpi_reply;
-       u32 iounit_pg1_flags;
-
-       mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
-       if (ioc->ir_firmware)
-               mpt2sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
-                   &ioc->manu_pg10);
-       mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
-       mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
-       mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
-       mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
-       mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
-       mpt2sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8);
-       _base_display_ioc_capabilities(ioc);
-
-       /*
-        * Enable task_set_full handling in iounit_pg1 when the
-        * facts capabilities indicate that its supported.
-        */
-       iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
-       if ((ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
-               iounit_pg1_flags &=
-                   ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
-       else
-               iounit_pg1_flags |=
-                   MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
-       ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
-       mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
-
-       if (ioc->iounit_pg8.NumSensors)
-               ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors;
-}
-
-/**
- * _base_release_memory_pools - release memory
- * @ioc: per adapter object
- *
- * Free memory allocated from _base_allocate_memory_pools.
- *
- * Return nothing.
- */
-static void
-_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
-{
-       int i = 0;
-       struct reply_post_struct *rps;
-
-       dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       if (ioc->request) {
-               pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
-                   ioc->request,  ioc->request_dma);
-               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
-                   ": free\n", ioc->name, ioc->request));
-               ioc->request = NULL;
-       }
-
-       if (ioc->sense) {
-               pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
-               if (ioc->sense_dma_pool)
-                       pci_pool_destroy(ioc->sense_dma_pool);
-               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
-                   ": free\n", ioc->name, ioc->sense));
-               ioc->sense = NULL;
-       }
-
-       if (ioc->reply) {
-               pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
-               if (ioc->reply_dma_pool)
-                       pci_pool_destroy(ioc->reply_dma_pool);
-               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
-                    ": free\n", ioc->name, ioc->reply));
-               ioc->reply = NULL;
-       }
-
-       if (ioc->reply_free) {
-               pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
-                   ioc->reply_free_dma);
-               if (ioc->reply_free_dma_pool)
-                       pci_pool_destroy(ioc->reply_free_dma_pool);
-               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
-                   "(0x%p): free\n", ioc->name, ioc->reply_free));
-               ioc->reply_free = NULL;
-       }
-
-       if (ioc->reply_post) {
-               do {
-                       rps = &ioc->reply_post[i];
-                       if (rps->reply_post_free) {
-                               pci_pool_free(
-                                   ioc->reply_post_free_dma_pool,
-                                   rps->reply_post_free,
-                                   rps->reply_post_free_dma);
-                               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                                   "reply_post_free_pool(0x%p): free\n",
-                                   ioc->name, rps->reply_post_free));
-                               rps->reply_post_free = NULL;
-                       }
-               } while (ioc->rdpq_array_enable &&
-                          (++i < ioc->reply_queue_count));
-
-               if (ioc->reply_post_free_dma_pool)
-                       pci_pool_destroy(ioc->reply_post_free_dma_pool);
-               kfree(ioc->reply_post);
-       }
-
-       if (ioc->config_page) {
-               dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "config_page(0x%p): free\n", ioc->name,
-                   ioc->config_page));
-               pci_free_consistent(ioc->pdev, ioc->config_page_sz,
-                   ioc->config_page, ioc->config_page_dma);
-       }
-
-       if (ioc->scsi_lookup) {
-               free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages);
-               ioc->scsi_lookup = NULL;
-       }
-       kfree(ioc->hpr_lookup);
-       kfree(ioc->internal_lookup);
-       if (ioc->chain_lookup) {
-               for (i = 0; i < ioc->chain_depth; i++) {
-                       if (ioc->chain_lookup[i].chain_buffer)
-                               pci_pool_free(ioc->chain_dma_pool,
-                                   ioc->chain_lookup[i].chain_buffer,
-                                   ioc->chain_lookup[i].chain_buffer_dma);
-               }
-               if (ioc->chain_dma_pool)
-                       pci_pool_destroy(ioc->chain_dma_pool);
-               free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
-               ioc->chain_lookup = NULL;
-       }
-}
-
-
-/**
- * _base_allocate_memory_pools - allocate start of day memory pools
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 success, anything else error
- */
-static int
-_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
-{
-       struct mpt2sas_facts *facts;
-       u16 max_sge_elements;
-       u16 chains_needed_per_io;
-       u32 sz, total_sz, reply_post_free_sz;
-       u32 retry_sz;
-       u16 max_request_credit;
-       int i;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       retry_sz = 0;
-       facts = &ioc->facts;
-
-       /* command line tunables  for max sgl entries */
-       if (max_sgl_entries != -1) {
-               ioc->shost->sg_tablesize =  min_t(unsigned short,
-                            max_sgl_entries, SCSI_MAX_SG_CHAIN_SEGMENTS);
-               if (ioc->shost->sg_tablesize > MPT2SAS_SG_DEPTH)
-                       printk(MPT2SAS_WARN_FMT
-                        "sg_tablesize(%u) is bigger than kernel defined"
-                        " SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name,
-                         ioc->shost->sg_tablesize, MPT2SAS_SG_DEPTH);
-       } else {
-               ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
-       }
-
-       /* command line tunables  for max controller queue depth */
-       if (max_queue_depth != -1 && max_queue_depth != 0) {
-               max_request_credit = min_t(u16, max_queue_depth +
-                       ioc->hi_priority_depth + ioc->internal_depth,
-                       facts->RequestCredit);
-               if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
-                       max_request_credit =  MAX_HBA_QUEUE_DEPTH;
-       } else
-               max_request_credit = min_t(u16, facts->RequestCredit,
-                   MAX_HBA_QUEUE_DEPTH);
-
-       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;
-
-       /* reply frame size */
-       ioc->reply_sz = facts->ReplyFrameSize * 4;
-
- retry_allocation:
-       total_sz = 0;
-       /* calculate number of sg elements left over in the 1st frame */
-       max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
-           sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
-       ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
-
-       /* now do the same for a chain buffer */
-       max_sge_elements = ioc->request_sz - ioc->sge_size;
-       ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
-
-       ioc->chain_offset_value_for_main_message =
-           ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
-            (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
-
-       /*
-        *  MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
-        */
-       chains_needed_per_io = ((ioc->shost->sg_tablesize -
-          ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
-           + 1;
-       if (chains_needed_per_io > facts->MaxChainDepth) {
-               chains_needed_per_io = facts->MaxChainDepth;
-               ioc->shost->sg_tablesize = min_t(u16,
-               ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
-               * chains_needed_per_io), ioc->shost->sg_tablesize);
-       }
-       ioc->chains_needed_per_io = chains_needed_per_io;
-
-       /* reply free queue sizing - taking into account for 64 FW events */
-       ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
-
-       /* calculate reply descriptor post queue depth */
-       ioc->reply_post_queue_depth = ioc->hba_queue_depth +
-                                       ioc->reply_free_queue_depth +  1;
-       /* align the reply post queue on the next 16 count boundary */
-       if (ioc->reply_post_queue_depth % 16)
-               ioc->reply_post_queue_depth += 16 -
-                       (ioc->reply_post_queue_depth % 16);
-
-
-       if (ioc->reply_post_queue_depth >
-           facts->MaxReplyDescriptorPostQueueDepth) {
-               ioc->reply_post_queue_depth =
-                       facts->MaxReplyDescriptorPostQueueDepth -
-                   (facts->MaxReplyDescriptorPostQueueDepth % 16);
-               ioc->hba_queue_depth =
-                       ((ioc->reply_post_queue_depth - 64) / 2) - 1;
-               ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
-       }
-
-       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));
-
-       /* reply post queue, 16 byte align */
-       reply_post_free_sz = ioc->reply_post_queue_depth *
-           sizeof(Mpi2DefaultReplyDescriptor_t);
-
-       sz = reply_post_free_sz;
-       if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable)
-               sz *= ioc->reply_queue_count;
-
-       ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ?
-           (ioc->reply_queue_count):1,
-           sizeof(struct reply_post_struct), GFP_KERNEL);
-
-       if (!ioc->reply_post) {
-               printk(MPT2SAS_ERR_FMT "reply_post_free pool: kcalloc failed\n",
-                       ioc->name);
-               goto out;
-       }
-       ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
-           ioc->pdev, sz, 16, 0);
-       if (!ioc->reply_post_free_dma_pool) {
-               printk(MPT2SAS_ERR_FMT
-                "reply_post_free pool: pci_pool_create failed\n",
-                ioc->name);
-               goto out;
-       }
-       i = 0;
-       do {
-               ioc->reply_post[i].reply_post_free =
-                   pci_pool_alloc(ioc->reply_post_free_dma_pool,
-                   GFP_KERNEL,
-                   &ioc->reply_post[i].reply_post_free_dma);
-               if (!ioc->reply_post[i].reply_post_free) {
-                       printk(MPT2SAS_ERR_FMT
-                       "reply_post_free pool: pci_pool_alloc failed\n",
-                       ioc->name);
-                       goto out;
-               }
-               memset(ioc->reply_post[i].reply_post_free, 0, sz);
-               dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "reply post free pool (0x%p): depth(%d),"
-                   "element_size(%d), pool_size(%d kB)\n", ioc->name,
-                   ioc->reply_post[i].reply_post_free,
-                   ioc->reply_post_queue_depth, 8, sz/1024));
-               dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "reply_post_free_dma = (0x%llx)\n", ioc->name,
-                   (unsigned long long)
-                   ioc->reply_post[i].reply_post_free_dma));
-               total_sz += sz;
-       } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
-
-       if (ioc->dma_mask == 64) {
-               if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
-                       printk(MPT2SAS_WARN_FMT
-                           "no suitable consistent DMA mask for %s\n",
-                           ioc->name, pci_name(ioc->pdev));
-                       goto out;
-               }
-       }
-
-       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;
-       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->scsiio_depth;
-       sz = ((ioc->scsiio_depth + 1) * 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: 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->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH)
-                       goto out;
-               retry_sz += 64;
-               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: 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);
-
-
-       /* 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);
-
-
-       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->hba_queue_depth, ioc->request_sz,
-           (ioc->hba_queue_depth * ioc->request_sz)/1024));
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
-           ioc->name, (unsigned long long) ioc->request_dma));
-       total_sz += sz;
-
-       sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
-       ioc->scsi_lookup_pages = get_order(sz);
-       ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
-           GFP_KERNEL, ioc->scsi_lookup_pages);
-       if (!ioc->scsi_lookup) {
-               printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
-                   "sz(%d)\n", ioc->name, (int)sz);
-               goto out;
-       }
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): "
-           "depth(%d)\n", ioc->name, ioc->request,
-           ioc->scsiio_depth));
-
-       ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
-       sz = ioc->chain_depth * sizeof(struct chain_tracker);
-       ioc->chain_pages = get_order(sz);
-
-       ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
-           GFP_KERNEL, ioc->chain_pages);
-       if (!ioc->chain_lookup) {
-               printk(MPT2SAS_ERR_FMT "chain_lookup: get_free_pages failed, "
-                   "sz(%d)\n", ioc->name, (int)sz);
-               goto out;
-       }
-       ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
-           ioc->request_sz, 16, 0);
-       if (!ioc->chain_dma_pool) {
-               printk(MPT2SAS_ERR_FMT "chain_dma_pool: pci_pool_create "
-                   "failed\n", ioc->name);
-               goto out;
-       }
-       for (i = 0; i < ioc->chain_depth; i++) {
-               ioc->chain_lookup[i].chain_buffer = pci_pool_alloc(
-                   ioc->chain_dma_pool , GFP_KERNEL,
-                   &ioc->chain_lookup[i].chain_buffer_dma);
-               if (!ioc->chain_lookup[i].chain_buffer) {
-                       ioc->chain_depth = i;
-                       goto chain_done;
-               }
-               total_sz += ioc->request_sz;
-       }
-chain_done:
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool depth"
-           "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
-           ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
-           ioc->request_sz))/1024));
-
-       /* 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->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
-       ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
-           0);
-       if (!ioc->sense_dma_pool) {
-               printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
-                   ioc->name);
-               goto out;
-       }
-       ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
-           &ioc->sense_dma);
-       if (!ioc->sense) {
-               printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
-                   ioc->name);
-               goto out;
-       }
-       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->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));
-       total_sz += sz;
-
-       /* reply pool, 4 byte align */
-       sz = ioc->reply_free_queue_depth * ioc->reply_sz;
-       ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
-           0);
-       if (!ioc->reply_dma_pool) {
-               printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
-                   ioc->name);
-               goto out;
-       }
-       ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
-           &ioc->reply_dma);
-       if (!ioc->reply) {
-               printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
-                   ioc->name);
-               goto out;
-       }
-       ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
-       ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
-           "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
-           ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
-           ioc->name, (unsigned long long)ioc->reply_dma));
-       total_sz += sz;
-
-       /* reply free queue, 16 byte align */
-       sz = ioc->reply_free_queue_depth * 4;
-       ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
-           ioc->pdev, sz, 16, 0);
-       if (!ioc->reply_free_dma_pool) {
-               printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
-                   "failed\n", ioc->name);
-               goto out;
-       }
-       ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
-           &ioc->reply_free_dma);
-       if (!ioc->reply_free) {
-               printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
-                   "failed\n", ioc->name);
-               goto out;
-       }
-       memset(ioc->reply_free, 0, sz);
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
-           "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
-           ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
-           "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
-       total_sz += sz;
-
-       ioc->config_page_sz = 512;
-       ioc->config_page = pci_alloc_consistent(ioc->pdev,
-           ioc->config_page_sz, &ioc->config_page_dma);
-       if (!ioc->config_page) {
-               printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
-                   "failed\n", ioc->name);
-               goto out;
-       }
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
-           "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
-           "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
-       total_sz += ioc->config_page_sz;
-
-       printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
-           ioc->name, total_sz/1024);
-       printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
-           "Max Controller Queue Depth(%d)\n",
-           ioc->name, ioc->shost->can_queue, facts->RequestCredit);
-       printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
-           ioc->name, ioc->shost->sg_tablesize);
-       return 0;
-
- out:
-       return -ENOMEM;
-}
-
-
-/**
- * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
- * @ioc: Pointer to MPT_ADAPTER structure
- * @cooked: Request raw or cooked IOC state
- *
- * Returns all IOC Doorbell register bits if cooked==0, else just the
- * Doorbell bits in MPI_IOC_STATE_MASK.
- */
-u32
-mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
-{
-       u32 s, sc;
-
-       s = readl(&ioc->chip->Doorbell);
-       sc = s & MPI2_IOC_STATE_MASK;
-       return cooked ? sc : s;
-}
-
-/**
- * _base_wait_on_iocstate - waiting on a particular ioc state
- * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
-    int sleep_flag)
-{
-       u32 count, cntdn;
-       u32 current_state;
-
-       count = 0;
-       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-       do {
-               current_state = mpt2sas_base_get_iocstate(ioc, 1);
-               if (current_state == ioc_state)
-                       return 0;
-               if (count && current_state == MPI2_IOC_STATE_FAULT)
-                       break;
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(1);
-               else
-                       udelay(500);
-               count++;
-       } while (--cntdn);
-
-       return current_state;
-}
-
-/**
- * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
- * a write to the doorbell)
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
- */
-static int
-_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
-    int sleep_flag)
-{
-       u32 cntdn, count;
-       u32 int_status;
-
-       count = 0;
-       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-       do {
-               int_status = readl(&ioc->chip->HostInterruptStatus);
-               if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
-                       dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                           "successful count(%d), timeout(%d)\n", ioc->name,
-                           __func__, count, timeout));
-                       return 0;
-               }
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(1);
-               else
-                       udelay(500);
-               count++;
-       } while (--cntdn);
-
-       printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-           "int_status(%x)!\n", ioc->name, __func__, count, int_status);
-       return -EFAULT;
-}
-
-/**
- * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
- * doorbell.
- */
-static int
-_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
-    int sleep_flag)
-{
-       u32 cntdn, count;
-       u32 int_status;
-       u32 doorbell;
-
-       count = 0;
-       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-       do {
-               int_status = readl(&ioc->chip->HostInterruptStatus);
-               if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
-                       dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                           "successful count(%d), timeout(%d)\n", ioc->name,
-                           __func__, count, timeout));
-                       return 0;
-               } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
-                       doorbell = readl(&ioc->chip->Doorbell);
-                       if ((doorbell & MPI2_IOC_STATE_MASK) ==
-                           MPI2_IOC_STATE_FAULT) {
-                               mpt2sas_base_fault_info(ioc , doorbell);
-                               return -EFAULT;
-                       }
-               } else if (int_status == 0xFFFFFFFF)
-                       goto out;
-
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(1);
-               else
-                       udelay(500);
-               count++;
-       } while (--cntdn);
-
- out:
-       printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-           "int_status(%x)!\n", ioc->name, __func__, count, int_status);
-       return -EFAULT;
-}
-
-/**
- * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
- * @ioc: per adapter object
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
-    int sleep_flag)
-{
-       u32 cntdn, count;
-       u32 doorbell_reg;
-
-       count = 0;
-       cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
-       do {
-               doorbell_reg = readl(&ioc->chip->Doorbell);
-               if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
-                       dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                           "successful count(%d), timeout(%d)\n", ioc->name,
-                           __func__, count, timeout));
-                       return 0;
-               }
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(1);
-               else
-                       udelay(500);
-               count++;
-       } while (--cntdn);
-
-       printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
-           "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
-       return -EFAULT;
-}
-
-/**
- * _base_send_ioc_reset - send doorbell reset
- * @ioc: per adapter object
- * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
-    int sleep_flag)
-{
-       u32 ioc_state;
-       int r = 0;
-
-       if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
-               printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
-                   ioc->name, __func__);
-               return -EFAULT;
-       }
-
-       if (!(ioc->facts.IOCCapabilities &
-          MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
-               return -EFAULT;
-
-       printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
-
-       writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
-           &ioc->chip->Doorbell);
-       if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
-               r = -EFAULT;
-               goto out;
-       }
-       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
-           timeout, sleep_flag);
-       if (ioc_state) {
-               printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
-                   " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
-               r = -EFAULT;
-               goto out;
-       }
- out:
-       printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
-           ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
-       return r;
-}
-
-/**
- * _base_handshake_req_reply_wait - send request thru doorbell interface
- * @ioc: per adapter object
- * @request_bytes: request length
- * @request: pointer having request payload
- * @reply_bytes: reply length
- * @reply: pointer to reply payload
- * @timeout: timeout in second
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
-    u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
-{
-       MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
-       int i;
-       u8 failed;
-       u16 dummy;
-       __le32 *mfp;
-
-       /* make sure doorbell is not in use */
-       if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
-               printk(MPT2SAS_ERR_FMT "doorbell is in use "
-                   " (line=%d)\n", ioc->name, __LINE__);
-               return -EFAULT;
-       }
-
-       /* clear pending doorbell interrupts from previous state changes */
-       if (readl(&ioc->chip->HostInterruptStatus) &
-           MPI2_HIS_IOC2SYS_DB_STATUS)
-               writel(0, &ioc->chip->HostInterruptStatus);
-
-       /* send message to ioc */
-       writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
-           ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
-           &ioc->chip->Doorbell);
-
-       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;
-       }
-       writel(0, &ioc->chip->HostInterruptStatus);
-
-       if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
-               printk(MPT2SAS_ERR_FMT "doorbell handshake "
-                   "ack failed (line=%d)\n", ioc->name, __LINE__);
-               return -EFAULT;
-       }
-
-       /* send message 32-bits at a time */
-       for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
-               writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
-               if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
-                       failed = 1;
-       }
-
-       if (failed) {
-               printk(MPT2SAS_ERR_FMT "doorbell handshake "
-                   "sending request failed (line=%d)\n", ioc->name, __LINE__);
-               return -EFAULT;
-       }
-
-       /* now wait for the reply */
-       if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
-               printk(MPT2SAS_ERR_FMT "doorbell handshake "
-                  "int failed (line=%d)\n", ioc->name, __LINE__);
-               return -EFAULT;
-       }
-
-       /* read the first two 16-bits, it gives the total length of the reply */
-       reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-           & MPI2_DOORBELL_DATA_MASK);
-       writel(0, &ioc->chip->HostInterruptStatus);
-       if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
-               printk(MPT2SAS_ERR_FMT "doorbell handshake "
-                  "int failed (line=%d)\n", ioc->name, __LINE__);
-               return -EFAULT;
-       }
-       reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-           & MPI2_DOORBELL_DATA_MASK);
-       writel(0, &ioc->chip->HostInterruptStatus);
-
-       for (i = 2; i < default_reply->MsgLength * 2; i++)  {
-               if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
-                       printk(MPT2SAS_ERR_FMT "doorbell "
-                           "handshake int failed (line=%d)\n", ioc->name,
-                           __LINE__);
-                       return -EFAULT;
-               }
-               if (i >=  reply_bytes/2) /* overflow case */
-                       dummy = readl(&ioc->chip->Doorbell);
-               else
-                       reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
-                           & MPI2_DOORBELL_DATA_MASK);
-               writel(0, &ioc->chip->HostInterruptStatus);
-       }
-
-       _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
-       if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
-               dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
-                   " (line=%d)\n", ioc->name, __LINE__));
-       }
-       writel(0, &ioc->chip->HostInterruptStatus);
-
-       if (ioc->logging_level & MPT_DEBUG_INIT) {
-               mfp = (__le32 *)reply;
-               printk(KERN_INFO "\toffset:data\n");
-               for (i = 0; i < reply_bytes/4; i++)
-                       printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
-                           le32_to_cpu(mfp[i]));
-       }
-       return 0;
-}
-
-/**
- * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
- * @ioc: per adapter object
- * @mpi_reply: the reply payload from FW
- * @mpi_request: the request payload sent to FW
- *
- * The SAS IO Unit Control Request message allows the host to perform low-level
- * operations, such as resets on the PHYs of the IO Unit, also allows the host
- * to obtain the IOC assigned device handles for a device if it has other
- * identifying information about the device, in addition allows the host to
- * remove IOC resources associated with the device.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2SasIoUnitControlReply_t *mpi_reply,
-    Mpi2SasIoUnitControlRequest_t *mpi_request)
-{
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       bool issue_reset = false;
-       int rc;
-       void *request;
-       u16 wait_state_count;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       mutex_lock(&ioc->base_cmds.mutex);
-
-       if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       rc = 0;
-       ioc->base_cmds.status = MPT2_CMD_PENDING;
-       request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->base_cmds.smid = smid;
-       memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
-       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;
-       init_completion(&ioc->base_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
-           msecs_to_jiffies(10000));
-       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)
-               ioc->ioc_link_reset_in_progress = 0;
-       if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SasIoUnitControlRequest_t)/4);
-               if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = true;
-               goto issue_host_reset;
-       }
-       if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
-               memcpy(mpi_reply, ioc->base_cmds.reply,
-                   sizeof(Mpi2SasIoUnitControlReply_t));
-       else
-               memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       goto out;
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       rc = -EFAULT;
- out:
-       mutex_unlock(&ioc->base_cmds.mutex);
-       return rc;
-}
-
-
-/**
- * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
- * @ioc: per adapter object
- * @mpi_reply: the reply payload from FW
- * @mpi_request: the request payload sent to FW
- *
- * The SCSI Enclosure Processor request message causes the IOC to
- * communicate with SES devices to control LED status signals.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
-{
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       bool issue_reset = false;
-       int rc;
-       void *request;
-       u16 wait_state_count;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       mutex_lock(&ioc->base_cmds.mutex);
-
-       if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       rc = 0;
-       ioc->base_cmds.status = MPT2_CMD_PENDING;
-       request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->base_cmds.smid = smid;
-       memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
-       init_completion(&ioc->base_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
-           msecs_to_jiffies(10000));
-       if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SepRequest_t)/4);
-               if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = true;
-               goto issue_host_reset;
-       }
-       if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
-               memcpy(mpi_reply, ioc->base_cmds.reply,
-                   sizeof(Mpi2SepReply_t));
-       else
-               memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       goto out;
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       rc = -EFAULT;
- out:
-       mutex_unlock(&ioc->base_cmds.mutex);
-       return rc;
-}
-
-/**
- * _base_get_port_facts - obtain port facts reply and save in ioc
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
-{
-       Mpi2PortFactsRequest_t mpi_request;
-       Mpi2PortFactsReply_t mpi_reply;
-       struct mpt2sas_port_facts *pfacts;
-       int mpi_reply_sz, mpi_request_sz, r;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
-       mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
-       memset(&mpi_request, 0, mpi_request_sz);
-       mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
-       mpi_request.PortNumber = port;
-       r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
-           (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
-
-       if (r != 0) {
-               printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
-                   ioc->name, __func__, r);
-               return r;
-       }
-
-       pfacts = &ioc->pfacts[port];
-       memset(pfacts, 0, sizeof(struct mpt2sas_port_facts));
-       pfacts->PortNumber = mpi_reply.PortNumber;
-       pfacts->VP_ID = mpi_reply.VP_ID;
-       pfacts->VF_ID = mpi_reply.VF_ID;
-       pfacts->MaxPostedCmdBuffers =
-           le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
-
-       return 0;
-}
-
-/**
- * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL
- * @ioc: per adapter object
- * @timeout:
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_wait_for_iocstate(struct MPT2SAS_ADAPTER *ioc, int timeout,
-       int sleep_flag)
-{
-       u32 ioc_state, doorbell;
-       int rc;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       if (ioc->pci_error_recovery)
-               return 0;
-
-       doorbell = mpt2sas_base_get_iocstate(ioc, 0);
-       ioc_state = doorbell & MPI2_IOC_STATE_MASK;
-       dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
-           ioc->name, __func__, ioc_state));
-
-       switch (ioc_state) {
-       case MPI2_IOC_STATE_READY:
-       case MPI2_IOC_STATE_OPERATIONAL:
-               return 0;
-       }
-
-       if (doorbell & MPI2_DOORBELL_USED) {
-               dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "unexpected doorbell activ!e\n", ioc->name));
-               goto issue_diag_reset;
-       }
-
-       if (ioc_state == MPI2_IOC_STATE_FAULT) {
-               mpt2sas_base_fault_info(ioc, doorbell &
-                   MPI2_DOORBELL_DATA_MASK);
-               goto issue_diag_reset;
-       }
-
-       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
-           timeout, sleep_flag);
-       if (ioc_state) {
-               printk(MPT2SAS_ERR_FMT
-                   "%s: failed going to ready state (ioc_state=0x%x)\n",
-                   ioc->name, __func__, ioc_state);
-               return -EFAULT;
-       }
-
- issue_diag_reset:
-       rc = _base_diag_reset(ioc, sleep_flag);
-       return rc;
-}
-
-/**
- * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
-       Mpi2IOCFactsRequest_t mpi_request;
-       Mpi2IOCFactsReply_t mpi_reply;
-       struct mpt2sas_facts *facts;
-       int mpi_reply_sz, mpi_request_sz, r;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       r = _base_wait_for_iocstate(ioc, 10, sleep_flag);
-       if (r) {
-               printk(MPT2SAS_ERR_FMT "%s: failed getting to correct state\n",
-                       ioc->name, __func__);
-               return r;
-       }
-
-       mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
-       mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
-       memset(&mpi_request, 0, mpi_request_sz);
-       mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
-       r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
-           (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
-
-       if (r != 0) {
-               printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
-                   ioc->name, __func__, r);
-               return r;
-       }
-
-       facts = &ioc->facts;
-       memset(facts, 0, sizeof(struct mpt2sas_facts));
-       facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
-       facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
-       facts->VP_ID = mpi_reply.VP_ID;
-       facts->VF_ID = mpi_reply.VF_ID;
-       facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
-       facts->MaxChainDepth = mpi_reply.MaxChainDepth;
-       facts->WhoInit = mpi_reply.WhoInit;
-       facts->NumberOfPorts = mpi_reply.NumberOfPorts;
-       facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors;
-       facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
-       facts->MaxReplyDescriptorPostQueueDepth =
-           le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
-       facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
-       facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
-       if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
-               ioc->ir_firmware = 1;
-       if ((facts->IOCCapabilities &
-             MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE))
-               ioc->rdpq_array_capable = 1;
-       facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
-       facts->IOCRequestFrameSize =
-           le16_to_cpu(mpi_reply.IOCRequestFrameSize);
-       facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
-       facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
-       ioc->shost->max_id = -1;
-       facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
-       facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
-       facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
-       facts->HighPriorityCredit =
-           le16_to_cpu(mpi_reply.HighPriorityCredit);
-       facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
-       facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
-           "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
-           facts->MaxChainDepth));
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
-           "reply frame size(%d)\n", ioc->name,
-           facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
-       return 0;
-}
-
-/**
- * _base_send_ioc_init - send ioc_init to firmware
- * @ioc: per adapter object
- * @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, int sleep_flag)
-{
-       Mpi2IOCInitRequest_t mpi_request;
-       Mpi2IOCInitReply_t mpi_reply;
-       int i, r = 0;
-       struct timeval current_time;
-       u16 ioc_status;
-       u32 reply_post_free_array_sz = 0;
-       Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL;
-       dma_addr_t reply_post_free_array_dma;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       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 = 0; /* TODO */
-       mpi_request.VP_ID = 0;
-       mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
-       mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
-
-       if (_base_is_controller_msix_enabled(ioc))
-               mpi_request.HostMSIxVectors = ioc->reply_queue_count;
-       mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
-       mpi_request.ReplyDescriptorPostQueueDepth =
-           cpu_to_le16(ioc->reply_post_queue_depth);
-       mpi_request.ReplyFreeQueueDepth =
-           cpu_to_le16(ioc->reply_free_queue_depth);
-
-       mpi_request.SenseBufferAddressHigh =
-           cpu_to_le32((u64)ioc->sense_dma >> 32);
-       mpi_request.SystemReplyAddressHigh =
-           cpu_to_le32((u64)ioc->reply_dma >> 32);
-       mpi_request.SystemRequestFrameBaseAddress =
-           cpu_to_le64((u64)ioc->request_dma);
-       mpi_request.ReplyFreeQueueAddress =
-           cpu_to_le64((u64)ioc->reply_free_dma);
-
-       if (ioc->rdpq_array_enable) {
-               reply_post_free_array_sz = ioc->reply_queue_count *
-                   sizeof(Mpi2IOCInitRDPQArrayEntry);
-               reply_post_free_array = pci_alloc_consistent(ioc->pdev,
-                       reply_post_free_array_sz, &reply_post_free_array_dma);
-               if (!reply_post_free_array) {
-                       printk(MPT2SAS_ERR_FMT
-                       "reply_post_free_array: pci_alloc_consistent failed\n",
-                       ioc->name);
-                       r = -ENOMEM;
-                       goto out;
-               }
-               memset(reply_post_free_array, 0, reply_post_free_array_sz);
-               for (i = 0; i < ioc->reply_queue_count; i++)
-                       reply_post_free_array[i].RDPQBaseAddress =
-                           cpu_to_le64(
-                               (u64)ioc->reply_post[i].reply_post_free_dma);
-               mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE;
-               mpi_request.ReplyDescriptorPostQueueAddress =
-                   cpu_to_le64((u64)reply_post_free_array_dma);
-       } else {
-               mpi_request.ReplyDescriptorPostQueueAddress =
-                   cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma);
-       }
-
-       /* This time stamp specifies number of milliseconds
-        * since epoch ~ midnight January 1, 1970.
-        */
-       do_gettimeofday(&current_time);
-       mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 +
-           (current_time.tv_usec / 1000));
-
-       if (ioc->logging_level & MPT_DEBUG_INIT) {
-               __le32 *mfp;
-               int i;
-
-               mfp = (__le32 *)&mpi_request;
-               printk(KERN_INFO "\toffset:data\n");
-               for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
-                       printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
-                           le32_to_cpu(mfp[i]));
-       }
-
-       r = _base_handshake_req_reply_wait(ioc,
-           sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
-           sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
-           sleep_flag);
-
-       if (r != 0) {
-               printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
-                   ioc->name, __func__, r);
-               goto out;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS ||
-           mpi_reply.IOCLogInfo) {
-               printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
-               r = -EIO;
-       }
-
-out:
-       if (reply_post_free_array)
-               pci_free_consistent(ioc->pdev, reply_post_free_array_sz,
-                                   reply_post_free_array,
-                                   reply_post_free_array_dma);
-       return r;
-}
-
-/**
- * mpt2sas_port_enable_done - command completion routine for port enable
- * @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)
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-u8
-mpt2sas_port_enable_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
-       u32 reply)
-{
-       MPI2DefaultReply_t *mpi_reply;
-       u16 ioc_status;
-
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
-               return 1;
-
-       if (ioc->port_enable_cmds.status == MPT2_CMD_NOT_USED)
-               return 1;
-
-       ioc->port_enable_cmds.status |= MPT2_CMD_COMPLETE;
-       if (mpi_reply) {
-               ioc->port_enable_cmds.status |= MPT2_CMD_REPLY_VALID;
-               memcpy(ioc->port_enable_cmds.reply, mpi_reply,
-                   mpi_reply->MsgLength*4);
-       }
-       ioc->port_enable_cmds.status &= ~MPT2_CMD_PENDING;
-
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-               ioc->port_enable_failed = 1;
-
-       if (ioc->is_driver_loading) {
-               if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
-                       mpt2sas_port_enable_complete(ioc);
-                       return 1;
-               } else {
-                       ioc->start_scan_failed = ioc_status;
-                       ioc->start_scan = 0;
-                       return 1;
-               }
-       }
-       complete(&ioc->port_enable_cmds.done);
-       return 1;
-}
-
-
-/**
- * _base_send_port_enable - send port_enable(discovery stuff) to firmware
- * @ioc: per adapter object
- * @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, int sleep_flag)
-{
-       Mpi2PortEnableRequest_t *mpi_request;
-       Mpi2PortEnableReply_t *mpi_reply;
-       unsigned long timeleft;
-       int r = 0;
-       u16 smid;
-       u16 ioc_status;
-
-       printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
-
-       if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
-               printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-
-       ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->port_enable_cmds.smid = smid;
-       memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
-       mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-
-       init_completion(&ioc->port_enable_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done,
-           300*HZ);
-       if (!(ioc->port_enable_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2PortEnableRequest_t)/4);
-               if (ioc->port_enable_cmds.status & MPT2_CMD_RESET)
-                       r = -EFAULT;
-               else
-                       r = -ETIME;
-               goto out;
-       }
-       mpi_reply = ioc->port_enable_cmds.reply;
-
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "%s: failed with (ioc_status=0x%08x)\n",
-                   ioc->name, __func__, ioc_status);
-               r = -EFAULT;
-               goto out;
-       }
- out:
-       ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
-       printk(MPT2SAS_INFO_FMT "port enable: %s\n", ioc->name, ((r == 0) ?
-           "SUCCESS" : "FAILED"));
-       return r;
-}
-
-/**
- * mpt2sas_port_enable - initiate firmware discovery (don't wait for reply)
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2PortEnableRequest_t *mpi_request;
-       u16 smid;
-
-       printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
-
-       if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
-               printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->port_enable_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-
-       ioc->port_enable_cmds.status = MPT2_CMD_PENDING;
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->port_enable_cmds.smid = smid;
-       memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
-       mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
-
-       mpt2sas_base_put_smid_default(ioc, smid);
-       return 0;
-}
-
-/**
- * _base_determine_wait_on_discovery - desposition
- * @ioc: per adapter object
- *
- * Decide whether to wait on discovery to complete. Used to either
- * locate boot device, or report volumes ahead of physical devices.
- *
- * Returns 1 for wait, 0 for don't wait
- */
-static int
-_base_determine_wait_on_discovery(struct MPT2SAS_ADAPTER *ioc)
-{
-       /* We wait for discovery to complete if IR firmware is loaded.
-        * The sas topology events arrive before PD events, so we need time to
-        * turn on the bit in ioc->pd_handles to indicate PD
-        * Also, it maybe required to report Volumes ahead of physical
-        * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set.
-        */
-       if (ioc->ir_firmware)
-               return 1;
-
-       /* if no Bios, then we don't need to wait */
-       if (!ioc->bios_pg3.BiosVersion)
-               return 0;
-
-       /* Bios is present, then we drop down here.
-        *
-        * If there any entries in the Bios Page 2, then we wait
-        * for discovery to complete.
-        */
-
-       /* Current Boot Device */
-       if ((ioc->bios_pg2.CurrentBootDeviceForm &
-           MPI2_BIOSPAGE2_FORM_MASK) ==
-           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
-       /* Request Boot Device */
-          (ioc->bios_pg2.ReqBootDeviceForm &
-           MPI2_BIOSPAGE2_FORM_MASK) ==
-           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED &&
-       /* Alternate Request Boot Device */
-          (ioc->bios_pg2.ReqAltBootDeviceForm &
-           MPI2_BIOSPAGE2_FORM_MASK) ==
-           MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED)
-               return 0;
-
-       return 1;
-}
-
-
-/**
- * _base_unmask_events - turn on notification for this event
- * @ioc: per adapter object
- * @event: firmware event
- *
- * The mask is stored in ioc->event_masks.
- */
-static void
-_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
-{
-       u32 desired_event;
-
-       if (event >= 128)
-               return;
-
-       desired_event = (1 << (event % 32));
-
-       if (event < 32)
-               ioc->event_masks[0] &= ~desired_event;
-       else if (event < 64)
-               ioc->event_masks[1] &= ~desired_event;
-       else if (event < 96)
-               ioc->event_masks[2] &= ~desired_event;
-       else if (event < 128)
-               ioc->event_masks[3] &= ~desired_event;
-}
-
-/**
- * _base_event_notification - send event notification
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
-       Mpi2EventNotificationRequest_t *mpi_request;
-       unsigned long timeleft;
-       u16 smid;
-       int r = 0;
-       int i;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
-               printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               return -EAGAIN;
-       }
-       ioc->base_cmds.status = MPT2_CMD_PENDING;
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->base_cmds.smid = smid;
-       memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
-       mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
-       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] =
-                   cpu_to_le32(ioc->event_masks[i]);
-       init_completion(&ioc->base_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       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",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2EventNotificationRequest_t)/4);
-               if (ioc->base_cmds.status & MPT2_CMD_RESET)
-                       r = -EFAULT;
-               else
-                       r = -ETIME;
-       } else
-               dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: complete\n",
-                   ioc->name, __func__));
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-       return r;
-}
-
-/**
- * mpt2sas_base_validate_event_type - validating event types
- * @ioc: per adapter object
- * @event: firmware event
- *
- * This will turn on firmware event notification when application
- * ask for that event. We don't mask events that are already enabled.
- */
-void
-mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
-{
-       int i, j;
-       u32 event_mask, desired_event;
-       u8 send_update_to_fw;
-
-       for (i = 0, send_update_to_fw = 0; i <
-           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
-               event_mask = ~event_type[i];
-               desired_event = 1;
-               for (j = 0; j < 32; j++) {
-                       if (!(event_mask & desired_event) &&
-                           (ioc->event_masks[i] & desired_event)) {
-                               ioc->event_masks[i] &= ~desired_event;
-                               send_update_to_fw = 1;
-                       }
-                       desired_event = (desired_event << 1);
-               }
-       }
-
-       if (!send_update_to_fw)
-               return;
-
-       mutex_lock(&ioc->base_cmds.mutex);
-       _base_event_notification(ioc, CAN_SLEEP);
-       mutex_unlock(&ioc->base_cmds.mutex);
-}
-
-/**
- * _base_diag_reset - the "big hammer" start of day reset
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
-       u32 host_diagnostic;
-       u32 ioc_state;
-       u32 count;
-       u32 hcb_size;
-
-       printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
-       drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
-           ioc->name));
-
-       count = 0;
-       do {
-               /* Write magic sequence to WriteSequence register
-                * Loop until in diagnostic mode
-                */
-               drsprintk(ioc, printk(MPT2SAS_INFO_FMT "write magic "
-                   "sequence\n", ioc->name));
-               writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
-               writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
-
-               /* wait 100 msec */
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(100);
-               else
-                       mdelay(100);
-
-               if (count++ > 20)
-                       goto out;
-
-               host_diagnostic = readl(&ioc->chip->HostDiagnostic);
-               drsprintk(ioc, printk(MPT2SAS_INFO_FMT "wrote magic "
-                   "sequence: count(%d), host_diagnostic(0x%08x)\n",
-                   ioc->name, count, host_diagnostic));
-
-       } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
-
-       hcb_size = readl(&ioc->chip->HCBSize);
-
-       drsprintk(ioc, printk(MPT2SAS_INFO_FMT "diag reset: issued\n",
-           ioc->name));
-       writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
-            &ioc->chip->HostDiagnostic);
-
-       /* This delay allows the chip PCIe hardware time to finish reset tasks*/
-       if (sleep_flag == CAN_SLEEP)
-               msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
-       else
-               mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000);
-
-       /* Approximately 300 second max wait */
-       for (count = 0; count < (300000000 /
-           MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) {
-
-               host_diagnostic = readl(&ioc->chip->HostDiagnostic);
-
-               if (host_diagnostic == 0xFFFFFFFF)
-                       goto out;
-               if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
-                       break;
-
-               /* Wait to pass the second read delay window */
-               if (sleep_flag == CAN_SLEEP)
-                       msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
-                              /1000);
-               else
-                       mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC
-                              /1000);
-       }
-
-       if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
-
-               drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter "
-                   "assuming the HCB Address points to good F/W\n",
-                   ioc->name));
-               host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
-               host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
-               writel(host_diagnostic, &ioc->chip->HostDiagnostic);
-
-               drsprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "re-enable the HCDW\n", ioc->name));
-               writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
-                   &ioc->chip->HCBSize);
-       }
-
-       drsprintk(ioc, printk(MPT2SAS_INFO_FMT "restart the adapter\n",
-           ioc->name));
-       writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
-           &ioc->chip->HostDiagnostic);
-
-       drsprintk(ioc, printk(MPT2SAS_INFO_FMT "disable writes to the "
-           "diagnostic register\n", ioc->name));
-       writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
-
-       drsprintk(ioc, printk(MPT2SAS_INFO_FMT "Wait for FW to go to the "
-           "READY state\n", ioc->name));
-       ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
-           sleep_flag);
-       if (ioc_state) {
-               printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
-                   " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
-               goto out;
-       }
-
-       printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
-       return 0;
-
- out:
-       printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
-       return -EFAULT;
-}
-
-/**
- * _base_make_ioc_ready - put controller in READY state
- * @ioc: per adapter object
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- * @type: FORCE_BIG_HAMMER or SOFT_RESET
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
-    enum reset_type type)
-{
-       u32 ioc_state;
-       int rc;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       if (ioc->pci_error_recovery)
-               return 0;
-
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
-       dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
-           ioc->name, __func__, ioc_state));
-
-       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
-               return 0;
-
-       if (ioc_state & MPI2_DOORBELL_USED) {
-               dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
-                   "active!\n", ioc->name));
-               goto issue_diag_reset;
-       }
-
-       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
-               mpt2sas_base_fault_info(ioc, ioc_state &
-                   MPI2_DOORBELL_DATA_MASK);
-               goto issue_diag_reset;
-       }
-
-       if (type == FORCE_BIG_HAMMER)
-               goto issue_diag_reset;
-
-       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
-               if (!(_base_send_ioc_reset(ioc,
-                   MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) {
-                       ioc->ioc_reset_count++;
-                       return 0;
-       }
-
- issue_diag_reset:
-       rc = _base_diag_reset(ioc, CAN_SLEEP);
-       ioc->ioc_reset_count++;
-       return rc;
-}
-
-/**
- * _base_make_ioc_operational - put controller in OPERATIONAL state
- * @ioc: per adapter object
- * @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, int sleep_flag)
-{
-       int r, i;
-       unsigned long   flags;
-       u32 reply_address;
-       u16 smid;
-       struct _tr_list *delayed_tr, *delayed_tr_next;
-       u8 hide_flag;
-       struct adapter_reply_queue *reply_q;
-       long reply_post_free;
-       u32 reply_post_free_sz, index = 0;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_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);
-       }
-
-       list_for_each_entry_safe(delayed_tr, delayed_tr_next,
-           &ioc->delayed_tr_volume_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);
-       smid = 1;
-       for (i = 0; i < ioc->scsiio_depth; i++, smid++) {
-               INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list);
-               ioc->scsi_lookup[i].cb_idx = 0xFF;
-               ioc->scsi_lookup[i].smid = smid;
-               ioc->scsi_lookup[i].scmd = NULL;
-               ioc->scsi_lookup[i].direct_io = 0;
-               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);
-       }
-
-       /* chain pool */
-       INIT_LIST_HEAD(&ioc->free_chain_list);
-       for (i = 0; i < ioc->chain_depth; i++)
-               list_add_tail(&ioc->chain_lookup[i].tracker_list,
-                   &ioc->free_chain_list);
-
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
-       /* initialize Reply Free Queue */
-       for (i = 0, reply_address = (u32)ioc->reply_dma ;
-           i < ioc->reply_free_queue_depth ; i++, reply_address +=
-           ioc->reply_sz)
-               ioc->reply_free[i] = cpu_to_le32(reply_address);
-
-       /* initialize reply queues */
-       if (ioc->is_driver_loading)
-               _base_assign_reply_queues(ioc);
-
-       /* initialize Reply Post Free Queue */
-       reply_post_free_sz = ioc->reply_post_queue_depth *
-           sizeof(Mpi2DefaultReplyDescriptor_t);
-       reply_post_free = (long)ioc->reply_post[index].reply_post_free;
-       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-               reply_q->reply_post_host_index = 0;
-               reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
-                   reply_post_free;
-               for (i = 0; i < ioc->reply_post_queue_depth; i++)
-                       reply_q->reply_post_free[i].Words =
-                                                    cpu_to_le64(ULLONG_MAX);
-               if (!_base_is_controller_msix_enabled(ioc))
-                       goto skip_init_reply_post_free_queue;
-               /*
-                * If RDPQ is enabled, switch to the next allocation.
-                * Otherwise advance within the contiguous region.
-                */
-               if (ioc->rdpq_array_enable)
-                       reply_post_free = (long)
-                           ioc->reply_post[++index].reply_post_free;
-               else
-                       reply_post_free += reply_post_free_sz;
-       }
- skip_init_reply_post_free_queue:
-
-       r = _base_send_ioc_init(ioc, sleep_flag);
-       if (r)
-               return r;
-
-       /* initialize reply free host index */
-       ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
-       writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
-
-       /* initialize reply post host index */
-       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
-               writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT,
-                   &ioc->chip->ReplyPostHostIndex);
-               if (!_base_is_controller_msix_enabled(ioc))
-                       goto skip_init_reply_post_host_index;
-       }
-
- skip_init_reply_post_host_index:
-
-       _base_unmask_interrupts(ioc);
-
-       r = _base_event_notification(ioc, sleep_flag);
-       if (r)
-               return r;
-
-       if (sleep_flag == CAN_SLEEP)
-               _base_static_config_pages(ioc);
-
-
-       if (ioc->is_driver_loading) {
-               if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
-                   == 0x80) {
-                       hide_flag = (u8) (
-                           le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) &
-                           MFG_PAGE10_HIDE_SSDS_MASK);
-                       if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
-                               ioc->mfg_pg10_hide_flag = hide_flag;
-               }
-               ioc->wait_for_discovery_to_complete =
-                   _base_determine_wait_on_discovery(ioc);
-               return r; /* scan_start and scan_finished support */
-       }
-       r = _base_send_port_enable(ioc, sleep_flag);
-       if (r)
-               return r;
-
-       return r;
-}
-
-/**
- * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct pci_dev *pdev = ioc->pdev;
-
-       dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       /* synchronizing freeing resource with pci_access_mutex lock */
-       mutex_lock(&ioc->pci_access_mutex);
-       if (ioc->chip_phys && ioc->chip) {
-               _base_mask_interrupts(ioc);
-               ioc->shost_recovery = 1;
-               _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
-               ioc->shost_recovery = 0;
-       }
-
-       _base_free_irq(ioc);
-       _base_disable_msix(ioc);
-
-       if (ioc->chip_phys && ioc->chip)
-               iounmap(ioc->chip);
-       ioc->chip_phys = 0;
-
-       if (pci_is_enabled(pdev)) {
-               pci_release_selected_regions(ioc->pdev, ioc->bars);
-               pci_disable_pcie_error_reporting(pdev);
-               pci_disable_device(pdev);
-       }
-       mutex_unlock(&ioc->pci_access_mutex);
-       return;
-}
-
-/**
- * mpt2sas_base_attach - attach controller instance
- * @ioc: per adapter object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
-{
-       int r, i;
-       int cpu_id, last_cpu_id = 0;
-
-       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       /* setup cpu_msix_table */
-       ioc->cpu_count = num_online_cpus();
-       for_each_online_cpu(cpu_id)
-               last_cpu_id = cpu_id;
-       ioc->cpu_msix_table_sz = last_cpu_id + 1;
-       ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
-       ioc->reply_queue_count = 1;
-       if (!ioc->cpu_msix_table) {
-               dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
-                   "cpu_msix_table failed!!!\n", ioc->name));
-               r = -ENOMEM;
-               goto out_free_resources;
-       }
-
-       if (ioc->is_warpdrive) {
-               ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
-                   sizeof(resource_size_t *), GFP_KERNEL);
-               if (!ioc->reply_post_host_index) {
-                       dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation "
-                               "for cpu_msix_table failed!!!\n", ioc->name));
-                       r = -ENOMEM;
-                       goto out_free_resources;
-               }
-       }
-
-       ioc->rdpq_array_enable_assigned = 0;
-       ioc->dma_mask = 0;
-       r = mpt2sas_base_map_resources(ioc);
-       if (r)
-               goto out_free_resources;
-
-       if (ioc->is_warpdrive) {
-               ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
-                   &ioc->chip->ReplyPostHostIndex;
-
-               for (i = 1; i < ioc->cpu_msix_table_sz; i++)
-                       ioc->reply_post_host_index[i] =
-                       (resource_size_t __iomem *)
-                       ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
-                       * 4)));
-       }
-
-       pci_set_drvdata(ioc->pdev, ioc->shost);
-       r = _base_get_ioc_facts(ioc, CAN_SLEEP);
-       if (r)
-               goto out_free_resources;
-
-       r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
-       if (r)
-               goto out_free_resources;
-
-       ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
-           sizeof(struct mpt2sas_port_facts), GFP_KERNEL);
-       if (!ioc->pfacts) {
-               r = -ENOMEM;
-               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;
-
-       init_waitqueue_head(&ioc->reset_wq);
-       /* allocate memory pd handle bitmask list */
-       ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
-       if (ioc->facts.MaxDevHandle % 8)
-               ioc->pd_handles_sz++;
-       ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
-           GFP_KERNEL);
-       if (!ioc->pd_handles) {
-               r = -ENOMEM;
-               goto out_free_resources;
-       }
-       ioc->blocking_handles = kzalloc(ioc->pd_handles_sz,
-           GFP_KERNEL);
-       if (!ioc->blocking_handles) {
-               r = -ENOMEM;
-               goto out_free_resources;
-       }
-       ioc->fwfault_debug = mpt2sas_fwfault_debug;
-
-       /* base internal command bits */
-       mutex_init(&ioc->base_cmds.mutex);
-       ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-
-       /* port_enable command bits */
-       ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->port_enable_cmds.status = MPT2_CMD_NOT_USED;
-
-       /* transport internal command bits */
-       ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_init(&ioc->transport_cmds.mutex);
-
-       /* scsih internal command bits */
-       ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_init(&ioc->scsih_cmds.mutex);
-
-       /* task management internal command bits */
-       ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_init(&ioc->tm_cmds.mutex);
-
-       /* config page internal command bits */
-       ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_init(&ioc->config_cmds.mutex);
-
-       /* ctl module internal command bits */
-       ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
-       ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
-       ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_init(&ioc->ctl_cmds.mutex);
-
-       if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
-           !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
-           !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
-           !ioc->ctl_cmds.sense) {
-               r = -ENOMEM;
-               goto out_free_resources;
-       }
-
-       if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
-           !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
-           !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {
-               r = -ENOMEM;
-               goto out_free_resources;
-       }
-
-       for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
-               ioc->event_masks[i] = -1;
-
-       /* here we enable the events we care about */
-       _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
-       _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
-       _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
-       _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
-       _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
-       _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
-       _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
-       _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
-       _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
-       _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
-       _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD);
-       r = _base_make_ioc_operational(ioc, CAN_SLEEP);
-       if (r)
-               goto out_free_resources;
-
-       ioc->non_operational_loop = 0;
-
-       return 0;
-
- out_free_resources:
-
-       ioc->remove_host = 1;
-       mpt2sas_base_free_resources(ioc);
-       _base_release_memory_pools(ioc);
-       pci_set_drvdata(ioc->pdev, NULL);
-       kfree(ioc->cpu_msix_table);
-       if (ioc->is_warpdrive)
-               kfree(ioc->reply_post_host_index);
-       kfree(ioc->pd_handles);
-       kfree(ioc->blocking_handles);
-       kfree(ioc->tm_cmds.reply);
-       kfree(ioc->transport_cmds.reply);
-       kfree(ioc->scsih_cmds.reply);
-       kfree(ioc->config_cmds.reply);
-       kfree(ioc->base_cmds.reply);
-       kfree(ioc->port_enable_cmds.reply);
-       kfree(ioc->ctl_cmds.reply);
-       kfree(ioc->ctl_cmds.sense);
-       kfree(ioc->pfacts);
-       ioc->ctl_cmds.reply = NULL;
-       ioc->base_cmds.reply = NULL;
-       ioc->tm_cmds.reply = NULL;
-       ioc->scsih_cmds.reply = NULL;
-       ioc->transport_cmds.reply = NULL;
-       ioc->config_cmds.reply = NULL;
-       ioc->pfacts = NULL;
-       return r;
-}
-
-
-/**
- * mpt2sas_base_detach - remove controller instance
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
-{
-
-       dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       mpt2sas_base_stop_watchdog(ioc);
-       mpt2sas_base_free_resources(ioc);
-       _base_release_memory_pools(ioc);
-       pci_set_drvdata(ioc->pdev, NULL);
-       kfree(ioc->cpu_msix_table);
-       if (ioc->is_warpdrive)
-               kfree(ioc->reply_post_host_index);
-       kfree(ioc->pd_handles);
-       kfree(ioc->blocking_handles);
-       kfree(ioc->pfacts);
-       kfree(ioc->ctl_cmds.reply);
-       kfree(ioc->ctl_cmds.sense);
-       kfree(ioc->base_cmds.reply);
-       kfree(ioc->port_enable_cmds.reply);
-       kfree(ioc->tm_cmds.reply);
-       kfree(ioc->transport_cmds.reply);
-       kfree(ioc->scsih_cmds.reply);
-       kfree(ioc->config_cmds.reply);
-}
-
-/**
- * _base_reset_handler - reset callback handler (for base)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-static void
-_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
-       mpt2sas_scsih_reset_handler(ioc, reset_phase);
-       mpt2sas_ctl_reset_handler(ioc, reset_phase);
-       switch (reset_phase) {
-       case MPT2_IOC_PRE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
-               break;
-       case MPT2_IOC_AFTER_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
-               if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->transport_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
-                       complete(&ioc->transport_cmds.done);
-               }
-               if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->base_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
-                       complete(&ioc->base_cmds.done);
-               }
-               if (ioc->port_enable_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->port_enable_failed = 1;
-                       ioc->port_enable_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->port_enable_cmds.smid);
-                       if (ioc->is_driver_loading) {
-                               ioc->start_scan_failed =
-                                   MPI2_IOCSTATUS_INTERNAL_ERROR;
-                               ioc->start_scan = 0;
-                               ioc->port_enable_cmds.status =
-                                               MPT2_CMD_NOT_USED;
-                       } else
-                               complete(&ioc->port_enable_cmds.done);
-
-               }
-               if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->config_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
-                       ioc->config_cmds.smid = USHRT_MAX;
-                       complete(&ioc->config_cmds.done);
-               }
-               break;
-       case MPT2_IOC_DONE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
-               break;
-       }
-}
-
-/**
- * _wait_for_commands_to_complete - reset controller
- * @ioc: Pointer to MPT_ADAPTER structure
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- *
- * This function waiting(3s) for all pending commands to complete
- * prior to putting controller in reset.
- */
-static void
-_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
-{
-       u32 ioc_state;
-       unsigned long flags;
-       u16 i;
-
-       ioc->pending_io_count = 0;
-       if (sleep_flag != CAN_SLEEP)
-               return;
-
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
-       if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
-               return;
-
-       /* pending command count */
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       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);
-
-       if (!ioc->pending_io_count)
-               return;
-
-       /* wait for pending commands to complete */
-       wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
-}
-
-/**
- * mpt2sas_base_hard_reset_handler - reset controller
- * @ioc: Pointer to MPT_ADAPTER structure
- * @sleep_flag: CAN_SLEEP or NO_SLEEP
- * @type: FORCE_BIG_HAMMER or SOFT_RESET
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
-    enum reset_type type)
-{
-       int r;
-       unsigned long flags;
-
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       if (ioc->pci_error_recovery) {
-               printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
-                   ioc->name, __func__);
-               r = 0;
-               goto out_unlocked;
-       }
-
-       if (mpt2sas_fwfault_debug)
-               mpt2sas_halt_firmware(ioc);
-
-       /* TODO - What we really should be doing is pulling
-        * out all the code associated with NO_SLEEP; its never used.
-        * That is legacy code from mpt fusion driver, ported over.
-        * I will leave this BUG_ON here for now till its been resolved.
-        */
-       BUG_ON(sleep_flag == NO_SLEEP);
-
-       /* wait for an active reset in progress to complete */
-       if (!mutex_trylock(&ioc->reset_in_progress_mutex)) {
-               do {
-                       ssleep(1);
-               } while (ioc->shost_recovery == 1);
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
-                   __func__));
-               return ioc->ioc_reset_in_progress_status;
-       }
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       ioc->shost_recovery = 1;
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-
-       _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
-       _wait_for_commands_to_complete(ioc, sleep_flag);
-       _base_mask_interrupts(ioc);
-       r = _base_make_ioc_ready(ioc, sleep_flag, type);
-       if (r)
-               goto out;
-       _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
-
-       /* If this hard reset is called while port enable is active, then
-        * there is no reason to call make_ioc_operational
-        */
-       if (ioc->is_driver_loading && ioc->port_enable_failed) {
-               ioc->remove_host = 1;
-               r = -EFAULT;
-               goto out;
-       }
-
-       r = _base_get_ioc_facts(ioc, CAN_SLEEP);
-       if (r)
-               goto out;
-
-       if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable)
-               panic("%s: Issue occurred with flashing controller firmware."
-                     "Please reboot the system and ensure that the correct"
-                     " firmware version is running\n", ioc->name);
-
-       r = _base_make_ioc_operational(ioc, sleep_flag);
-       if (!r)
-               _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
- out:
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %s\n",
-           ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
-
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       ioc->ioc_reset_in_progress_status = r;
-       ioc->shost_recovery = 0;
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-       mutex_unlock(&ioc->reset_in_progress_mutex);
-
- out_unlocked:
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
-           __func__));
-       return r;
-}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
deleted file mode 100644 (file)
index 97ea360..0000000
+++ /dev/null
@@ -1,1235 +0,0 @@
-/*
- * This is the Fusion MPT base driver providing common API layer interface
- * for access to MPT (Message Passing Technology) firmware.
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.h
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_BASE_H_INCLUDED
-#define MPT2SAS_BASE_H_INCLUDED
-
-#include "mpi/mpi2_type.h"
-#include "mpi/mpi2.h"
-#include "mpi/mpi2_ioc.h"
-#include "mpi/mpi2_cnfg.h"
-#include "mpi/mpi2_init.h"
-#include "mpi/mpi2_raid.h"
-#include "mpi/mpi2_tool.h"
-#include "mpi/mpi2_sas.h"
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_transport_sas.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
-#include "mpt2sas_debug.h"
-
-/* driver versioning info */
-#define MPT2SAS_DRIVER_NAME            "mpt2sas"
-#define MPT2SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
-#define MPT2SAS_DESCRIPTION    "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION         "20.100.00.00"
-#define MPT2SAS_MAJOR_VERSION          20
-#define MPT2SAS_MINOR_VERSION          100
-#define MPT2SAS_BUILD_VERSION          00
-#define MPT2SAS_RELEASE_VERSION                00
-
-/*
- * Set MPT2SAS_SG_DEPTH value based on user input.
- */
-#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
-#if     CONFIG_SCSI_MPT2SAS_MAX_SGE  < 16
-#define MPT2SAS_SG_DEPTH       16
-#elif CONFIG_SCSI_MPT2SAS_MAX_SGE  > 128
-#define MPT2SAS_SG_DEPTH       128
-#else
-#define MPT2SAS_SG_DEPTH       CONFIG_SCSI_MPT2SAS_MAX_SGE
-#endif
-#else
-#define MPT2SAS_SG_DEPTH       128 /* MAX_HW_SEGMENTS */
-#endif
-
-
-/*
- * Generic Defines
- */
-#define MPT2SAS_SATA_QUEUE_DEPTH       32
-#define MPT2SAS_SAS_QUEUE_DEPTH                254
-#define MPT2SAS_RAID_QUEUE_DEPTH       128
-
-#define MPT_NAME_LENGTH                        32      /* generic length of strings */
-#define MPT_STRING_LENGTH              64
-
-#define MPT_MAX_CALLBACKS              16
-
-
-#define         CAN_SLEEP                      1
-#define  NO_SLEEP                      0
-
-#define INTERNAL_CMDS_COUNT            10      /* reserved cmds */
-
-#define MPI2_HIM_MASK                  0xFFFFFFFF /* mask every bit*/
-
-#define MPT2SAS_INVALID_DEVICE_HANDLE  0xFFFF
-
-
-/*
- * reset phases
- */
-#define MPT2_IOC_PRE_RESET             1 /* prior to host reset */
-#define MPT2_IOC_AFTER_RESET           2 /* just after host reset */
-#define MPT2_IOC_DONE_RESET            3 /* links re-initialized */
-
-/*
- * logging format
- */
-#define MPT2SAS_FMT                    "%s: "
-#define MPT2SAS_INFO_FMT               KERN_INFO MPT2SAS_FMT
-#define MPT2SAS_NOTE_FMT               KERN_NOTICE MPT2SAS_FMT
-#define MPT2SAS_WARN_FMT               KERN_WARNING MPT2SAS_FMT
-#define MPT2SAS_ERR_FMT                        KERN_ERR MPT2SAS_FMT
-
-/*
- * Dell HBA branding
- */
-#define MPT2SAS_DELL_BRANDING_SIZE                 32
-
-#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING        "Dell 6Gbps SAS HBA"
-#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING    "Dell PERC H200 Adapter"
-#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
-#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING    "Dell PERC H200 Modular"
-#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING   "Dell PERC H200 Embedded"
-#define MPT2SAS_DELL_PERC_H200_BRANDING            "Dell PERC H200"
-#define MPT2SAS_DELL_6GBPS_SAS_BRANDING            "Dell 6Gbps SAS"
-
-/*
- * Dell HBA SSDIDs
- */
-#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID           0x1F1C
-#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID       0x1F1D
-#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID    0x1F1E
-#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID       0x1F1F
-#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID      0x1F20
-#define MPT2SAS_DELL_PERC_H200_SSDID               0x1F21
-#define MPT2SAS_DELL_6GBPS_SAS_SSDID               0x1F22
-
-/*
- * Intel HBA branding
- */
-#define MPT2SAS_INTEL_RMS25JB080_BRANDING    \
-                               "Intel(R) Integrated RAID Module RMS25JB080"
-#define MPT2SAS_INTEL_RMS25JB040_BRANDING    \
-                               "Intel(R) Integrated RAID Module RMS25JB040"
-#define MPT2SAS_INTEL_RMS25KB080_BRANDING    \
-                               "Intel(R) Integrated RAID Module RMS25KB080"
-#define MPT2SAS_INTEL_RMS25KB040_BRANDING    \
-                               "Intel(R) Integrated RAID Module RMS25KB040"
-#define MPT2SAS_INTEL_RMS25LB040_BRANDING      \
-                               "Intel(R) Integrated RAID Module RMS25LB040"
-#define MPT2SAS_INTEL_RMS25LB080_BRANDING      \
-                               "Intel(R) Integrated RAID Module RMS25LB080"
-#define MPT2SAS_INTEL_RMS2LL080_BRANDING       \
-                               "Intel Integrated RAID Module RMS2LL080"
-#define MPT2SAS_INTEL_RMS2LL040_BRANDING       \
-                               "Intel Integrated RAID Module RMS2LL040"
-#define MPT2SAS_INTEL_RS25GB008_BRANDING       \
-                               "Intel(R) RAID Controller RS25GB008"
-#define MPT2SAS_INTEL_SSD910_BRANDING          \
-                               "Intel(R) SSD 910 Series"
-/*
- * Intel HBA SSDIDs
- */
-#define MPT2SAS_INTEL_RMS25JB080_SSDID         0x3516
-#define MPT2SAS_INTEL_RMS25JB040_SSDID         0x3517
-#define MPT2SAS_INTEL_RMS25KB080_SSDID         0x3518
-#define MPT2SAS_INTEL_RMS25KB040_SSDID         0x3519
-#define MPT2SAS_INTEL_RMS25LB040_SSDID         0x351A
-#define MPT2SAS_INTEL_RMS25LB080_SSDID         0x351B
-#define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
-#define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
-#define MPT2SAS_INTEL_RS25GB008_SSDID          0x3000
-#define MPT2SAS_INTEL_SSD910_SSDID             0x3700
-
-/*
- * HP HBA branding
- */
-#define MPT2SAS_HP_3PAR_SSVID                0x1590
-#define MPT2SAS_HP_2_4_INTERNAL_BRANDING        "HP H220 Host Bus Adapter"
-#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING        "HP H221 Host Bus Adapter"
-#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING "HP H222 Host Bus Adapter"
-#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING    "HP H220i Host Bus Adapter"
-#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING    "HP H210i Host Bus Adapter"
-
-/*
- * HO HBA SSDIDs
- */
-#define MPT2SAS_HP_2_4_INTERNAL_SSDID            0x0041
-#define MPT2SAS_HP_2_4_EXTERNAL_SSDID            0x0042
-#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID    0x0043
-#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID        0x0044
-#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID        0x0046
-
-/*
- *  WarpDrive Specific Log codes
- */
-
-#define MPT2_WARPDRIVE_LOGENTRY                (0x8002)
-#define MPT2_WARPDRIVE_LC_SSDT         (0x41)
-#define MPT2_WARPDRIVE_LC_SSDLW                (0x43)
-#define MPT2_WARPDRIVE_LC_SSDLF                (0x44)
-#define MPT2_WARPDRIVE_LC_BRMF         (0x4D)
-
-/*
- * per target private data
- */
-#define MPT_TARGET_FLAGS_RAID_COMPONENT        0x01
-#define MPT_TARGET_FLAGS_VOLUME                0x02
-#define MPT_TARGET_FLAGS_DELETED       0x04
-
-/**
- * struct MPT2SAS_TARGET - starget private hostdata
- * @starget: starget object
- * @sas_address: target sas address
- * @raid_device: raid_device pointer to access volume data
- * @handle: device handle
- * @num_luns: number luns
- * @flags: MPT_TARGET_FLAGS_XXX flags
- * @deleted: target flaged for deletion
- * @tm_busy: target is busy with TM request.
- * @sdev: The sas_device associated with this target
- */
-struct MPT2SAS_TARGET {
-       struct scsi_target *starget;
-       u64     sas_address;
-       struct _raid_device *raid_device;
-       u16     handle;
-       int     num_luns;
-       u32     flags;
-       u8      deleted;
-       u8      tm_busy;
-       struct _sas_device *sdev;
-};
-
-
-/*
- * per device private data
- */
-#define MPT_DEVICE_FLAGS_INIT          0x01
-#define MPT_DEVICE_TLR_ON              0x02
-
-/**
- * struct MPT2SAS_DEVICE - sdev private hostdata
- * @sas_target: starget private hostdata
- * @lun: lun number
- * @flags: MPT_DEVICE_XXX flags
- * @configured_lun: lun is configured
- * @block: device is in SDEV_BLOCK state
- * @tlr_snoop_check: flag used in determining whether to disable TLR
- */
-
-/* OEM Identifiers */
-#define MFG10_OEM_ID_INVALID                   (0x00000000)
-#define MFG10_OEM_ID_DELL                      (0x00000001)
-#define MFG10_OEM_ID_FSC                       (0x00000002)
-#define MFG10_OEM_ID_SUN                       (0x00000003)
-#define MFG10_OEM_ID_IBM                       (0x00000004)
-
-/* GENERIC Flags 0*/
-#define MFG10_GF0_OCE_DISABLED                 (0x00000001)
-#define MFG10_GF0_R1E_DRIVE_COUNT              (0x00000002)
-#define MFG10_GF0_R10_DISPLAY                  (0x00000004)
-#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE       (0x00000008)
-#define MFG10_GF0_SINGLE_DRIVE_R0              (0x00000010)
-
-/* OEM Specific Flags will come from OEM specific header files */
-typedef struct _MPI2_CONFIG_PAGE_MAN_10 {
-    MPI2_CONFIG_PAGE_HEADER Header;                                 /* 00h */
-    U8                      OEMIdentifier;                          /* 04h */
-    U8                      Reserved1;                              /* 05h */
-    U16                     Reserved2;                              /* 08h */
-    U32                     Reserved3;                              /* 0Ch */
-    U32                     GenericFlags0;                          /* 10h */
-    U32                     GenericFlags1;                          /* 14h */
-    U32                     Reserved4;                              /* 18h */
-    U32                     OEMSpecificFlags0;                      /* 1Ch */
-    U32                     OEMSpecificFlags1;                      /* 20h */
-    U32                     Reserved5[18];                          /* 24h-60h*/
-} MPI2_CONFIG_PAGE_MAN_10,
-  MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_10,
-  Mpi2ManufacturingPage10_t, MPI2_POINTER pMpi2ManufacturingPage10_t;
-
-#define MFG_PAGE10_HIDE_SSDS_MASK      (0x00000003)
-#define MFG_PAGE10_HIDE_ALL_DISKS      (0x00)
-#define MFG_PAGE10_EXPOSE_ALL_DISKS    (0x01)
-#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02)
-
-
-struct MPT2SAS_DEVICE {
-       struct MPT2SAS_TARGET *sas_target;
-       unsigned int    lun;
-       u32     flags;
-       u8      configured_lun;
-       u8      block;
-       u8      tlr_snoop_check;
-};
-
-#define MPT2_CMD_NOT_USED      0x8000  /* free */
-#define MPT2_CMD_COMPLETE      0x0001  /* completed */
-#define MPT2_CMD_PENDING       0x0002  /* pending */
-#define MPT2_CMD_REPLY_VALID   0x0004  /* reply is valid */
-#define MPT2_CMD_RESET         0x0008  /* host reset dropped the command */
-
-/**
- * struct _internal_cmd - internal commands struct
- * @mutex: mutex
- * @done: completion
- * @reply: reply message pointer
- * @sense: sense data
- * @status: MPT2_CMD_XXX status
- * @smid: system message id
- */
-struct _internal_cmd {
-       struct mutex mutex;
-       struct completion done;
-       void    *reply;
-       void    *sense;
-       u16     status;
-       u16     smid;
-};
-
-
-/**
- * struct _sas_device - attached device information
- * @list: sas device list
- * @starget: starget object
- * @sas_address: device sas address
- * @device_name: retrieved from the SAS IDENTIFY frame.
- * @handle: device handle
- * @sas_address_parent: sas address of parent expander or sas host
- * @enclosure_handle: enclosure handle
- * @enclosure_logical_id: enclosure logical identifier
- * @volume_handle: volume handle (valid when hidden raid member)
- * @volume_wwid: volume unique identifier
- * @device_info: bitfield provides detailed info about the device
- * @id: target id
- * @channel: target channel
- * @slot: number number
- * @phy: phy identifier provided in sas device page 0
- * @responding: used in _scsih_sas_device_mark_responding
- * @pfa_led_on: flag for PFA LED status
- */
-struct _sas_device {
-       struct list_head list;
-       struct scsi_target *starget;
-       u64     sas_address;
-       u64     device_name;
-       u16     handle;
-       u64     sas_address_parent;
-       u16     enclosure_handle;
-       u64     enclosure_logical_id;
-       u16     volume_handle;
-       u64     volume_wwid;
-       u32     device_info;
-       int     id;
-       int     channel;
-       u16     slot;
-       u8      phy;
-       u8      responding;
-       u8      pfa_led_on;
-       struct kref refcount;
-};
-
-static inline void sas_device_get(struct _sas_device *s)
-{
-       kref_get(&s->refcount);
-}
-
-static inline void sas_device_free(struct kref *r)
-{
-       kfree(container_of(r, struct _sas_device, refcount));
-}
-
-static inline void sas_device_put(struct _sas_device *s)
-{
-       kref_put(&s->refcount, sas_device_free);
-}
-
-/**
- * struct _raid_device - raid volume link list
- * @list: sas device list
- * @starget: starget object
- * @sdev: scsi device struct (volumes are single lun)
- * @wwid: unique identifier for the volume
- * @handle: device handle
- * @block_size: Block size of the volume
- * @id: target id
- * @channel: target channel
- * @volume_type: the raid level
- * @device_info: bitfield provides detailed info about the hidden components
- * @num_pds: number of hidden raid components
- * @responding: used in _scsih_raid_device_mark_responding
- * @percent_complete: resync percent complete
- * @direct_io_enabled: Whether direct io to PDs are allowed or not
- * @stripe_exponent: X where 2powX is the stripe sz in blocks
- * @block_exponent: X where 2powX is the block sz in bytes
- * @max_lba: Maximum number of LBA in the volume
- * @stripe_sz: Stripe Size of the volume
- * @device_info: Device info of the volume member disk
- * @pd_handle: Array of handles of the physical drives for direct I/O in le16
- */
-#define MPT_MAX_WARPDRIVE_PDS          8
-struct _raid_device {
-       struct list_head list;
-       struct scsi_target *starget;
-       struct scsi_device *sdev;
-       u64     wwid;
-       u16     handle;
-       u16     block_sz;
-       int     id;
-       int     channel;
-       u8      volume_type;
-       u8      num_pds;
-       u8      responding;
-       u8      percent_complete;
-       u8      direct_io_enabled;
-       u8      stripe_exponent;
-       u8      block_exponent;
-       u64     max_lba;
-       u32     stripe_sz;
-       u32     device_info;
-       u16     pd_handle[MPT_MAX_WARPDRIVE_PDS];
-};
-
-/**
- * struct _boot_device - boot device info
- * @is_raid: flag to indicate whether this is volume
- * @device: holds pointer for either struct _sas_device or
- *     struct _raid_device
- */
-struct _boot_device {
-       u8 is_raid;
-       void *device;
-};
-
-/**
- * struct _sas_port - wide/narrow sas port information
- * @port_list: list of ports belonging to expander
- * @num_phys: number of phys belonging to this port
- * @remote_identify: attached device identification
- * @rphy: sas transport rphy object
- * @port: sas transport wide/narrow port object
- * @phy_list: _sas_phy list objects belonging to this port
- */
-struct _sas_port {
-       struct list_head port_list;
-       u8      num_phys;
-       struct sas_identify remote_identify;
-       struct sas_rphy *rphy;
-       struct sas_port *port;
-       struct list_head phy_list;
-};
-
-/**
- * struct _sas_phy - phy information
- * @port_siblings: list of phys belonging to a port
- * @identify: phy identification
- * @remote_identify: attached device identification
- * @phy: sas transport phy object
- * @phy_id: unique phy id
- * @handle: device handle for this phy
- * @attached_handle: device handle for attached device
- * @phy_belongs_to_port: port has been created for this phy
- */
-struct _sas_phy {
-       struct list_head port_siblings;
-       struct sas_identify identify;
-       struct sas_identify remote_identify;
-       struct sas_phy *phy;
-       u8      phy_id;
-       u16     handle;
-       u16     attached_handle;
-       u8      phy_belongs_to_port;
-};
-
-/**
- * struct _sas_node - sas_host/expander information
- * @list: list of expanders
- * @parent_dev: parent device class
- * @num_phys: number phys belonging to this sas_host/expander
- * @sas_address: sas address of this sas_host/expander
- * @handle: handle for this sas_host/expander
- * @sas_address_parent: sas address of parent expander or sas host
- * @enclosure_handle: handle for this a member of an enclosure
- * @device_info: bitwise defining capabilities of this sas_host/expander
- * @responding: used in _scsih_expander_device_mark_responding
- * @phy: a list of phys that make up this sas_host/expander
- * @sas_port_list: list of ports attached to this sas_host/expander
- */
-struct _sas_node {
-       struct list_head list;
-       struct device *parent_dev;
-       u8      num_phys;
-       u64     sas_address;
-       u16     handle;
-       u64     sas_address_parent;
-       u16     enclosure_handle;
-       u64     enclosure_logical_id;
-       u8      responding;
-       struct  _sas_phy *phy;
-       struct list_head sas_port_list;
-};
-
-/**
- * enum reset_type - reset state
- * @FORCE_BIG_HAMMER: issue diagnostic reset
- * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
- */
-enum reset_type {
-       FORCE_BIG_HAMMER,
-       SOFT_RESET,
-};
-
-/**
- * struct chain_tracker - firmware chain tracker
- * @chain_buffer: chain buffer
- * @chain_buffer_dma: physical address
- * @tracker_list: list of free request (ioc->free_chain_list)
- */
-struct chain_tracker {
-       void *chain_buffer;
-       dma_addr_t chain_buffer_dma;
-       struct list_head tracker_list;
-};
-
-/**
- * struct scsiio_tracker - scsi mf request tracker
- * @smid: system message id
- * @scmd: scsi request pointer
- * @cb_idx: callback index
- * @direct_io: To indicate whether I/O is direct (WARPDRIVE)
- * @chain_list: list of chains associated to this IO
- * @tracker_list: list of free request (ioc->free_list)
- */
-struct scsiio_tracker {
-       u16     smid;
-       struct scsi_cmnd *scmd;
-       u8      cb_idx;
-       u8      direct_io;
-       struct list_head chain_list;
-       struct list_head tracker_list;
-};
-
-/**
- * struct request_tracker - firmware request tracker
- * @smid: system message id
- * @cb_idx: callback index
- * @tracker_list: list of free request (ioc->free_list)
- */
-struct request_tracker {
-       u16     smid;
-       u8      cb_idx;
-       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);
-
-/**
- * struct adapter_reply_queue - the reply queue struct
- * @ioc: per adapter object
- * @msix_index: msix index into vector table
- * @vector: irq vector
- * @reply_post_host_index: head index in the pool where FW completes IO
- * @reply_post_free: reply post base virt address
- * @name: the name registered to request_irq()
- * @busy: isr is actively processing replies on another cpu
- * @list: this list
-*/
-struct adapter_reply_queue {
-       struct MPT2SAS_ADAPTER  *ioc;
-       u8                      msix_index;
-       unsigned int            vector;
-       u32                     reply_post_host_index;
-       Mpi2ReplyDescriptorsUnion_t *reply_post_free;
-       char                    name[MPT_NAME_LENGTH];
-       atomic_t                busy;
-       cpumask_var_t           affinity_hint;
-       struct list_head        list;
-};
-
-/* IOC Facts and Port Facts converted from little endian to cpu */
-union mpi2_version_union {
-       MPI2_VERSION_STRUCT             Struct;
-       u32                             Word;
-};
-
-struct mpt2sas_facts {
-       u16                     MsgVersion;
-       u16                     HeaderVersion;
-       u8                      IOCNumber;
-       u8                      VP_ID;
-       u8                      VF_ID;
-       u16                     IOCExceptions;
-       u16                     IOCStatus;
-       u32                     IOCLogInfo;
-       u8                      MaxChainDepth;
-       u8                      WhoInit;
-       u8                      NumberOfPorts;
-       u8                      MaxMSIxVectors;
-       u16                     RequestCredit;
-       u16                     ProductID;
-       u32                     IOCCapabilities;
-       union mpi2_version_union        FWVersion;
-       u16                     IOCRequestFrameSize;
-       u16                     Reserved3;
-       u16                     MaxInitiators;
-       u16                     MaxTargets;
-       u16                     MaxSasExpanders;
-       u16                     MaxEnclosures;
-       u16                     ProtocolFlags;
-       u16                     HighPriorityCredit;
-       u16                     MaxReplyDescriptorPostQueueDepth;
-       u8                      ReplyFrameSize;
-       u8                      MaxVolumes;
-       u16                     MaxDevHandle;
-       u16                     MaxPersistentEntries;
-       u16                     MinDevHandle;
-};
-
-struct mpt2sas_port_facts {
-       u8                      PortNumber;
-       u8                      VP_ID;
-       u8                      VF_ID;
-       u8                      PortType;
-       u16                     MaxPostedCmdBuffers;
-};
-
-struct reply_post_struct {
-       Mpi2ReplyDescriptorsUnion_t     *reply_post_free;
-       dma_addr_t                      reply_post_free_dma;
-};
-
-/**
- * enum mutex_type - task management mutex type
- * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it
- * @TM_MUTEX_ON: mutex is required
- */
-enum mutex_type {
-       TM_MUTEX_OFF = 0,
-       TM_MUTEX_ON = 1,
-};
-
-typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc);
-/**
- * struct MPT2SAS_ADAPTER - per adapter struct
- * @list: ioc_list
- * @shost: shost object
- * @id: unique adapter id
- * @cpu_count: number online cpus
- * @name: generic ioc string
- * @tmp_string: tmp string used for logging
- * @pdev: pci pdev object
- * @chip: memory mapped register space
- * @chip_phys: physical addrss prior to mapping
- * @logging_level: see mpt2sas_debug.h
- * @fwfault_debug: debuging FW timeouts
- * @ir_firmware: IR firmware present
- * @bars: bitmask of BAR's that must be configured
- * @mask_interrupts: ignore interrupt
- * @dma_mask: used to set the consistent dma mask
- * @fault_reset_work_q_name: fw fault work queue
- * @fault_reset_work_q: ""
- * @fault_reset_work: ""
- * @firmware_event_name: fw event work queue
- * @firmware_event_thread: ""
- * @fw_events_off: flag to turn off fw event handling
- * @fw_event_lock:
- * @fw_event_list: list of fw events
- * @aen_event_read_flag: event log was read
- * @broadcast_aen_busy: broadcast aen waiting to be serviced
- * @shost_recovery: host reset in progress
- * @ioc_reset_in_progress_lock:
- * @ioc_link_reset_in_progress: phy/hard reset in progress
- * @ignore_loginfos: ignore loginfos during task management
- * @remove_host: flag for when driver unloads, to avoid sending dev resets
- * @pci_error_recovery: flag to prevent ioc access until slot reset completes
- * @wait_for_discovery_to_complete: flag set at driver load time when
- *                                               waiting on reporting devices
- * @is_driver_loading: flag set at driver load time
- * @port_enable_failed: flag set when port enable has failed
- * @start_scan: flag set from scan_start callback, cleared from _mpt2sas_fw_work
- * @start_scan_failed: means port enable failed, return's the ioc_status
- * @msix_enable: flag indicating msix is enabled
- * @msix_vector_count: number msix vectors
- * @cpu_msix_table: table for mapping cpus to msix index
- * @cpu_msix_table_sz: table size
- * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands
- * @scsi_io_cb_idx: shost generated commands
- * @tm_cb_idx: task management commands
- * @scsih_cb_idx: scsih internal commands
- * @transport_cb_idx: transport internal commands
- * @ctl_cb_idx: clt internal commands
- * @base_cb_idx: base internal commands
- * @config_cb_idx: base internal commands
- * @tm_tr_cb_idx : device removal target reset handshake
- * @tm_tr_volume_cb_idx : volume removal target reset
- * @base_cmds:
- * @transport_cmds:
- * @scsih_cmds:
- * @tm_cmds:
- * @ctl_cmds:
- * @config_cmds:
- * @base_add_sg_single: handler for either 32/64 bit sgl's
- * @event_type: bits indicating which events to log
- * @event_context: unique id for each logged event
- * @event_log: event log pointer
- * @event_masks: events that are masked
- * @facts: static facts data
- * @pfacts: static port facts data
- * @manu_pg0: static manufacturing page 0
- * @manu_pg10: static manufacturing page 10
- * @bios_pg2: static bios page 2
- * @bios_pg3: static bios page 3
- * @ioc_pg8: static ioc page 8
- * @iounit_pg0: static iounit page 0
- * @iounit_pg1: static iounit page 1
- * @iounit_pg8: static iounit page 8
- * @sas_hba: sas host object
- * @sas_expander_list: expander object list
- * @sas_node_lock:
- * @sas_device_list: sas device object list
- * @sas_device_init_list: sas device object list (used only at init time)
- * @sas_device_lock:
- * @io_missing_delay: time for IO completed by fw when PDR enabled
- * @device_missing_delay: time for device missing by fw when PDR enabled
- * @sas_id : used for setting volume target IDs
- * @blocking_handles: bitmask used to identify which devices need blocking
- * @pd_handles : bitmask for PD handles
- * @pd_handles_sz : size of pd_handle bitmask
- * @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
- * @scsiio_depth: SCSI_IO queue depth
- * @request_sz: per request frame size
- * @request: pool of request frames
- * @request_dma:
- * @request_dma_sz:
- * @scsi_lookup: firmware request tracker list
- * @scsi_lookup_lock:
- * @free_list: free list of request
- * @chain: pool of chains
- * @pending_io_count:
- * @reset_wq:
- * @chain_dma:
- * @max_sges_in_main_message: number sg elements in main message
- * @max_sges_in_chain_message: number sg elements per chain
- * @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:
- * @reply_depth: hba reply queue depth:
- * @reply_sz: per reply frame size:
- * @reply: pool of replys:
- * @reply_dma:
- * @reply_dma_pool:
- * @reply_free_queue_depth: reply free depth
- * @reply_free: pool for reply free queue (32 bit addr)
- * @reply_free_dma:
- * @reply_free_dma_pool:
- * @reply_free_host_index: tail index in pool to insert free replys
- * @reply_post_queue_depth: reply post queue depth
- * @reply_post_struct: struct for reply_post_free physical & virt address
- * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init
- * @rdpq_array_enable: rdpq_array support is enabled in the driver
- * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag
- *                             is assigned only ones
- * @reply_queue_count: number of reply queue's
- * @reply_queue_list: link list contaning the reply queue info
- * @reply_post_host_index: head index in the pool where FW completes IO
- * @delayed_tr_list: target reset link list
- * @delayed_tr_volume_list: volume target reset link list
- * @@temp_sensors_count: flag to carry the number of temperature sensors
- * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and
- * pci resource handling. PCI resource freeing will lead to free
- * vital hardware/memory resource, which might be in use by cli/sysfs
- * path functions resulting in Null pointer reference followed by kernel
- * crash. To avoid the above race condition we use mutex syncrhonization
- * which ensures the syncrhonization between cli/sysfs_show path
- */
-struct MPT2SAS_ADAPTER {
-       struct list_head list;
-       struct Scsi_Host *shost;
-       u8              id;
-       int             cpu_count;
-       char            name[MPT_NAME_LENGTH];
-       char            tmp_string[MPT_STRING_LENGTH];
-       struct pci_dev  *pdev;
-       Mpi2SystemInterfaceRegs_t __iomem *chip;
-       resource_size_t chip_phys;
-       int             logging_level;
-       int             fwfault_debug;
-       u8              ir_firmware;
-       int             bars;
-       u8              mask_interrupts;
-       int             dma_mask;
-
-       /* fw fault handler */
-       char            fault_reset_work_q_name[20];
-       struct workqueue_struct *fault_reset_work_q;
-       struct delayed_work fault_reset_work;
-
-       /* fw event handler */
-       char            firmware_event_name[20];
-       struct workqueue_struct *firmware_event_thread;
-       spinlock_t      fw_event_lock;
-       struct list_head fw_event_list;
-
-        /* misc flags */
-       int             aen_event_read_flag;
-       u8              broadcast_aen_busy;
-       u16             broadcast_aen_pending;
-       u8              shost_recovery;
-
-       struct mutex    reset_in_progress_mutex;
-       spinlock_t      ioc_reset_in_progress_lock;
-       u8              ioc_link_reset_in_progress;
-       u8              ioc_reset_in_progress_status;
-
-       u8              ignore_loginfos;
-       u8              remove_host;
-       u8              pci_error_recovery;
-       u8              wait_for_discovery_to_complete;
-       struct completion       port_enable_done;
-       u8              is_driver_loading;
-       u8              port_enable_failed;
-
-       u8              start_scan;
-       u16             start_scan_failed;
-
-       u8              msix_enable;
-       u16             msix_vector_count;
-       u8              *cpu_msix_table;
-       resource_size_t __iomem **reply_post_host_index;
-       u16             cpu_msix_table_sz;
-       u32             ioc_reset_count;
-       MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
-       u32             non_operational_loop;
-
-       /* internal commands, callback index */
-       u8              scsi_io_cb_idx;
-       u8              tm_cb_idx;
-       u8              transport_cb_idx;
-       u8              scsih_cb_idx;
-       u8              ctl_cb_idx;
-       u8              base_cb_idx;
-       u8              port_enable_cb_idx;
-       u8              config_cb_idx;
-       u8              tm_tr_cb_idx;
-       u8              tm_tr_volume_cb_idx;
-       u8              tm_sas_control_cb_idx;
-       struct _internal_cmd base_cmds;
-       struct _internal_cmd port_enable_cmds;
-       struct _internal_cmd transport_cmds;
-       struct _internal_cmd scsih_cmds;
-       struct _internal_cmd tm_cmds;
-       struct _internal_cmd ctl_cmds;
-       struct _internal_cmd config_cmds;
-
-       MPT_ADD_SGE     base_add_sg_single;
-
-       /* event log */
-       u32             event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
-       u32             event_context;
-       void            *event_log;
-       u32             event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
-
-       /* static config pages */
-       struct mpt2sas_facts facts;
-       struct mpt2sas_port_facts *pfacts;
-       Mpi2ManufacturingPage0_t manu_pg0;
-       Mpi2BiosPage2_t bios_pg2;
-       Mpi2BiosPage3_t bios_pg3;
-       Mpi2IOCPage8_t ioc_pg8;
-       Mpi2IOUnitPage0_t iounit_pg0;
-       Mpi2IOUnitPage1_t iounit_pg1;
-       Mpi2IOUnitPage8_t iounit_pg8;
-
-       struct _boot_device req_boot_device;
-       struct _boot_device req_alt_boot_device;
-       struct _boot_device current_boot_device;
-
-       /* sas hba, expander, and device list */
-       struct _sas_node sas_hba;
-       struct list_head sas_expander_list;
-       spinlock_t      sas_node_lock;
-       struct list_head sas_device_list;
-       struct list_head sas_device_init_list;
-       spinlock_t      sas_device_lock;
-       struct list_head raid_device_list;
-       spinlock_t      raid_device_lock;
-       u8              io_missing_delay;
-       u16             device_missing_delay;
-       int             sas_id;
-       void            *blocking_handles;
-       void            *pd_handles;
-       u16             pd_handles_sz;
-
-       /* config page */
-       u16             config_page_sz;
-       void            *config_page;
-       dma_addr_t      config_page_dma;
-
-       /* scsiio request */
-       u16             hba_queue_depth;
-       u16             sge_size;
-       u16             scsiio_depth;
-       u16             request_sz;
-       u8              *request;
-       dma_addr_t      request_dma;
-       u32             request_dma_sz;
-       struct scsiio_tracker *scsi_lookup;
-       ulong           scsi_lookup_pages;
-       spinlock_t      scsi_lookup_lock;
-       struct list_head free_list;
-       int             pending_io_count;
-       wait_queue_head_t reset_wq;
-
-       /* chain */
-       struct chain_tracker *chain_lookup;
-       struct list_head free_chain_list;
-       struct dma_pool *chain_dma_pool;
-       ulong           chain_pages;
-       u16             max_sges_in_main_message;
-       u16             max_sges_in_chain_message;
-       u16             chains_needed_per_io;
-       u16             chain_offset_value_for_main_message;
-       u32             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;
-       struct dma_pool *sense_dma_pool;
-
-       /* reply */
-       u16             reply_sz;
-       u8              *reply;
-       dma_addr_t      reply_dma;
-       u32             reply_dma_max_address;
-       u32             reply_dma_min_address;
-       struct dma_pool *reply_dma_pool;
-
-       /* reply free queue */
-       u16             reply_free_queue_depth;
-       __le32          *reply_free;
-       dma_addr_t      reply_free_dma;
-       struct dma_pool *reply_free_dma_pool;
-       u32             reply_free_host_index;
-
-       /* reply post queue */
-       u16             reply_post_queue_depth;
-       struct reply_post_struct *reply_post;
-       u8              rdpq_array_capable;
-       u8              rdpq_array_enable;
-       u8              rdpq_array_enable_assigned;
-       struct dma_pool *reply_post_free_dma_pool;
-       u8              reply_queue_count;
-       struct list_head reply_queue_list;
-
-       struct list_head delayed_tr_list;
-       struct list_head delayed_tr_volume_list;
-       u8              temp_sensors_count;
-
-       /* diag buffer support */
-       u8              *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
-       u32             diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
-       dma_addr_t      diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
-       u8              diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
-       u32             unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
-       Mpi2ManufacturingPage10_t manu_pg10;
-       u32             product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
-       u32             diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
-       u32             ring_buffer_offset;
-       u32             ring_buffer_sz;
-       u8              is_warpdrive;
-       u8              hide_ir_msg;
-       u8              mfg_pg10_hide_flag;
-       u8              hide_drives;
-
-       struct mutex pci_access_mutex;
-};
-
-typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
-    u32 reply);
-
-
-/* base shared API */
-extern struct list_head mpt2sas_ioc_list;
-/* spinlock on list operations over IOCs
- * Case: when multiple warpdrive cards(IOCs) are in use
- * Each IOC will added to the ioc list stucture on initialization.
- * Watchdog threads run at regular intervals to check IOC for any
- * fault conditions which will trigger the dead_ioc thread to
- * deallocate pci resource, resulting deleting the IOC netry from list,
- * this deletion need to protected by spinlock to enusre that
- * ioc removal is syncrhonized, if not synchronized it might lead to
- * list_del corruption as the ioc list is traversed in cli path
- */
-extern spinlock_t gioc_lock;
-void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc);
-
-int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
-int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc);
-int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
-    enum reset_type type);
-
-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);
-__le32 mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc,
-    u16 smid);
-void mpt2sas_base_flush_reply_queues(struct MPT2SAS_ADAPTER *ioc);
-
-/* 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,
-    u16 handle);
-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,
-    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);
-
-u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
-    u32 reply);
-u8 mpt2sas_port_enable_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);
-
-void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code);
-int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t
-    *mpi_request);
-int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
-void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
-
-void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
-
-void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
-       u16 device_missing_delay, u8 io_missing_delay);
-
-int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
-
-/* scsih shared API */
-void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
-    u32 reply);
-int mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-       uint channel, uint id, uint lun, u8 type, u16 smid_task,
-       ulong timeout, enum mutex_type m_type);
-void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
-void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
-void mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-void mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
-               u64 sas_address);
-struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
-    u16 handle);
-struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
-    *ioc, u64 sas_address);
-struct _sas_device *mpt2sas_get_sdev_by_addr(
-    struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-struct _sas_device *__mpt2sas_get_sdev_by_addr(
-    struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
-
-void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc);
-void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
-
-/* config shared API */
-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);
-int mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page);
-int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2BiosPage2_t *config_page);
-int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2BiosPage3_t *config_page);
-int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2IOUnitPage0_t *config_page);
-int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz);
-int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2IOUnitPage1_t *config_page);
-int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2IOUnitPage1_t *config_page);
-int mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc,
-       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page);
-int mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc,
-       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz);
-int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
-int mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
-int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2IOCPage8_t *config_page);
-int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle);
-int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
-int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
-int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle);
-int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds);
-int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz);
-int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
-    u32 form_specific);
-int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
-    u16 *volume_handle);
-int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
-    u64 *wwid);
-/* ctl shared API */
-extern struct device_attribute *mpt2sas_host_attrs[];
-extern struct device_attribute *mpt2sas_dev_attrs[];
-void mpt2sas_ctl_init(void);
-void mpt2sas_ctl_exit(void);
-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 msix_index,
-    u32 reply);
-void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventNotificationReply_t *mpi_reply);
-
-void mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc,
-       u8 bits_to_regsiter);
-
-/* transport shared API */
-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, u64 sas_address);
-void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
-     u64 sas_address_parent);
-int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
-    *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
-int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
-    *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev);
-void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
-     u64 sas_address, u16 handle, u8 phy_number, u8 link_rate);
-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,
-                                       enum scsi_device_state new_state);
-
-#endif /* MPT2SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
deleted file mode 100644 (file)
index c43815b..0000000
+++ /dev/null
@@ -1,1527 +0,0 @@
-/*
- * This module provides common API for accessing firmware configuration pages
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include "mpt2sas_base.h"
-
-/* local definitions */
-
-/* Timeout for config page request (in seconds) */
-#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
-
-/* Common sgl flags for READING a config page. */
-#define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
-    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
-    | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
-
-/* Common sgl flags for WRITING a config page. */
-#define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
-    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
-    | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
-    << MPI2_SGE_FLAGS_SHIFT)
-
-/**
- * struct config_request - obtain dma memory via routine
- * @sz: size
- * @page: virt pointer
- * @page_dma: phys pointer
- *
- */
-struct config_request{
-       u16                     sz;
-       void                    *page;
-       dma_addr_t              page_dma;
-};
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _config_display_some_debug - debug routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @calling_function_name: string pass from calling function
- * @mpi_reply: reply message frame
- * Context: none.
- *
- * Function for displaying debug info helpful when debugging issues
- * in this module.
- */
-static void
-_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
-{
-       Mpi2ConfigRequest_t *mpi_request;
-       char *desc = NULL;
-
-       if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
-               return;
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
-       case MPI2_CONFIG_PAGETYPE_IO_UNIT:
-               desc = "io_unit";
-               break;
-       case MPI2_CONFIG_PAGETYPE_IOC:
-               desc = "ioc";
-               break;
-       case MPI2_CONFIG_PAGETYPE_BIOS:
-               desc = "bios";
-               break;
-       case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
-               desc = "raid_volume";
-               break;
-       case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
-               desc = "manufaucturing";
-               break;
-       case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
-               desc = "physdisk";
-               break;
-       case MPI2_CONFIG_PAGETYPE_EXTENDED:
-               switch (mpi_request->ExtPageType) {
-               case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
-                       desc = "sas_io_unit";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
-                       desc = "sas_expander";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
-                       desc = "sas_device";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
-                       desc = "sas_phy";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_LOG:
-                       desc = "log";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
-                       desc = "enclosure";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
-                       desc = "raid_config";
-                       break;
-               case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
-                       desc = "driver_mapping";
-                       break;
-               }
-               break;
-       }
-
-       if (!desc)
-               return;
-
-       printk(MPT2SAS_INFO_FMT "%s: %s(%d), action(%d), form(0x%08x), "
-           "smid(%d)\n", ioc->name, calling_function_name, desc,
-           mpi_request->Header.PageNumber, mpi_request->Action,
-           le32_to_cpu(mpi_request->PageAddress), smid);
-
-       if (!mpi_reply)
-               return;
-
-       if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
-               printk(MPT2SAS_INFO_FMT
-                   "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
-                   le32_to_cpu(mpi_reply->IOCLogInfo));
-}
-#endif
-
-/**
- * _config_alloc_config_dma_memory - obtain physical memory
- * @ioc: per adapter object
- * @mem: struct config_request
- *
- * A wrapper for obtaining dma-able memory for config page request.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
-    struct config_request *mem)
-{
-       int r = 0;
-
-       if (mem->sz > ioc->config_page_sz) {
-               mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz,
-                   &mem->page_dma, GFP_KERNEL);
-               if (!mem->page) {
-                       printk(MPT2SAS_ERR_FMT "%s: dma_alloc_coherent"
-                           " failed asking for (%d) bytes!!\n",
-                           ioc->name, __func__, mem->sz);
-                       r = -ENOMEM;
-               }
-       } else { /* use tmp buffer if less than 512 bytes */
-               mem->page = ioc->config_page;
-               mem->page_dma = ioc->config_page_dma;
-       }
-       return r;
-}
-
-/**
- * _config_free_config_dma_memory - wrapper to free the memory
- * @ioc: per adapter object
- * @mem: struct config_request
- *
- * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static void
-_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
-    struct config_request *mem)
-{
-       if (mem->sz > ioc->config_page_sz)
-               dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page,
-                   mem->page_dma);
-}
-
-/**
- * mpt2sas_config_done - config page 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: none.
- *
- * The callback handler when using _config_request.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-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 1;
-       if (ioc->config_cmds.smid != smid)
-               return 1;
-       ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
-       mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (mpi_reply) {
-               ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
-               memcpy(ioc->config_cmds.reply, mpi_reply,
-                   mpi_reply->MsgLength*4);
-       }
-       ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
-#endif
-       ioc->config_cmds.smid = USHRT_MAX;
-       complete(&ioc->config_cmds.done);
-       return 1;
-}
-
-/**
- * _config_request - main routine for sending config page requests
- * @ioc: per adapter object
- * @mpi_request: request message frame
- * @mpi_reply: reply mf payload returned from firmware
- * @timeout: timeout in seconds
- * @config_page: contents of the config page
- * @config_page_sz: size of config page
- * Context: sleep
- *
- * A generic API for config page requests to firmware.
- *
- * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling
- * this API.
- *
- * The callback index is set inside `ioc->config_cb_idx.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
-    *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout,
-    void *config_page, u16 config_page_sz)
-{
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       Mpi2ConfigRequest_t *config_request;
-       int r;
-       u8 retry_count, issue_host_reset = 0;
-       u16 wait_state_count;
-       struct config_request mem;
-
-       mutex_lock(&ioc->config_cmds.mutex);
-       if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
-                   ioc->name, __func__);
-               mutex_unlock(&ioc->config_cmds.mutex);
-               return -EAGAIN;
-       }
-
-       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;
-               mpi_request->Header.PageType = mpi_reply->Header.PageType;
-               mpi_request->Header.PageLength = mpi_reply->Header.PageLength;
-               mpi_request->ExtPageLength = mpi_reply->ExtPageLength;
-               mpi_request->ExtPageType = mpi_reply->ExtPageType;
-               if (mpi_request->Header.PageLength)
-                       mem.sz = mpi_request->Header.PageLength * 4;
-               else
-                       mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
-               r = _config_alloc_config_dma_memory(ioc, &mem);
-               if (r != 0)
-                       goto out;
-               if (mpi_request->Action ==
-                   MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
-                   mpi_request->Action ==
-                   MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
-                       ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
-                           MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz,
-                           mem.page_dma);
-                       memcpy(mem.page, config_page, min_t(u16, mem.sz,
-                           config_page_sz));
-               } else {
-                       memset(config_page, 0, config_page_sz);
-                       ioc->base_add_sg_single(&mpi_request->PageBufferSGE,
-                           MPT2_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma);
-               }
-       }
-
- retry_config:
-       if (retry_count) {
-               if (retry_count > 2) { /* attempt only 2 retries */
-                       r = -EFAULT;
-                       goto free_mem;
-               }
-               printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
-                   ioc->name, __func__, retry_count);
-       }
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-                       r = -EFAULT;
-                       goto free_mem;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-               r = -EAGAIN;
-               goto free_mem;
-       }
-
-       r = 0;
-       memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
-       ioc->config_cmds.status = MPT2_CMD_PENDING;
-       config_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->config_cmds.smid = smid;
-       memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       _config_display_some_debug(ioc, smid, "config_request", NULL);
-#endif
-       init_completion(&ioc->config_cmds.done);
-       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)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2ConfigRequest_t)/4);
-               retry_count++;
-               if (ioc->config_cmds.smid == smid)
-                       mpt2sas_base_free_smid(ioc, smid);
-               if ((ioc->shost_recovery) || (ioc->config_cmds.status &
-                   MPT2_CMD_RESET) || ioc->pci_error_recovery)
-                       goto retry_config;
-               issue_host_reset = 1;
-               r = -EFAULT;
-               goto free_mem;
-       }
-
-       if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
-               memcpy(mpi_reply, ioc->config_cmds.reply,
-                   sizeof(Mpi2ConfigReply_t));
-       if (retry_count)
-               printk(MPT2SAS_INFO_FMT "%s: retry (%d) completed!!\n",
-                   ioc->name, __func__, retry_count);
-       if (config_page && mpi_request->Action ==
-           MPI2_CONFIG_ACTION_PAGE_READ_CURRENT)
-               memcpy(config_page, mem.page, min_t(u16, mem.sz,
-                   config_page_sz));
- free_mem:
-       if (config_page)
-               _config_free_config_dma_memory(ioc, &mem);
- out:
-       ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_unlock(&ioc->config_cmds.mutex);
-
-       if (issue_host_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-       return r;
-}
-
-/**
- * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_manufacturing_pg10 - obtain manufacturing page 10
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_manufacturing_pg10(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage10_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
-       mpi_request.Header.PageNumber = 10;
-       mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_bios_pg2 - obtain bios page 2
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
-       mpi_request.Header.PageNumber = 2;
-       mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_bios_pg3 - obtain bios page 3
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2BiosPage3_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
-       mpi_request.Header.PageNumber = 3;
-       mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_set_iounit_pg1 - set iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg3 - obtain iounit page 3
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg3(struct MPT2SAS_ADAPTER *ioc,
-       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
-       mpi_request.Header.PageNumber = 3;
-       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_iounit_pg8 - obtain iounit page 8
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_iounit_pg8(struct MPT2SAS_ADAPTER *ioc,
-       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
-       mpi_request.Header.PageNumber = 8;
-       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
-       mpi_request.Header.PageNumber = 8;
-       mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: device handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
-       mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
-       mpi_request.Header.PageNumber = 0;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: device handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
-       mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
-       mpi_request.Header.PageNumber = 1;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
- * @ioc: per adapter object
- * @num_phys: pointer returned with the number of phys
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-       u16 ioc_status;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasIOUnitPage0_t config_page;
-
-       *num_phys = 0;
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
-           sizeof(Mpi2SasIOUnitPage0_t));
-       if (!r) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
-                       *num_phys = config_page.NumPhys;
-       }
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_set_sas_iounit_pg1 - send sas iounit page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Calling function should call config_get_number_hba_phys prior to
- * this function, so enough memory is allocated for config_page.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_set_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
-       _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_expander_pg0 - obtain expander page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_expander_pg1 - obtain expander page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
-    u16 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress =
-           cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
-           (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: expander handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_phy_pg0 - obtain phy page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress =
-           cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_phy_pg1 - obtain phy page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @phy_number: phy number
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress =
-           cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: volume handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
-    u32 handle)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
-       mpi_request.Header.PageNumber = 1;
-       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
- * @ioc: per adapter object
- * @handle: volume handle
- * @num_pds: returns pds count
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-    u8 *num_pds)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       Mpi2RaidVolPage0_t config_page;
-       Mpi2ConfigReply_t mpi_reply;
-       int r;
-       u16 ioc_status;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       *num_pds = 0;
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress =
-           cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page,
-           sizeof(Mpi2RaidVolPage0_t));
-       if (!r) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_SUCCESS)
-                       *num_pds = config_page.NumPhysDisks;
-       }
-
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_HANDLE or HANDLE
- * @handle: volume handle
- * @sz: size of buffer passed in config_page
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
-    u32 handle, u16 sz)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | handle);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
- * @ioc: per adapter object
- * @mpi_reply: reply mf payload returned from firmware
- * @config_page: contents of the config page
- * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
- * @form_specific: specific to the form
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
-    *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
-    u32 form_specific)
-{
-       Mpi2ConfigRequest_t mpi_request;
-       int r;
-
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
-       mpi_request.Header.PageNumber = 0;
-       mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.PageAddress = cpu_to_le32(form | form_specific);
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       r = _config_request(ioc, &mpi_request, mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-           sizeof(*config_page));
- out:
-       return r;
-}
-
-/**
- * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
- * @ioc: per adapter object
- * @pd_handle: phys disk handle
- * @volume_handle: volume handle
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
-    u16 *volume_handle)
-{
-       Mpi2RaidConfigurationPage0_t *config_page = NULL;
-       Mpi2ConfigRequest_t mpi_request;
-       Mpi2ConfigReply_t mpi_reply;
-       int r, i, config_page_sz;
-       u16 ioc_status;
-       int config_num;
-       u16 element_type;
-       u16 phys_disk_dev_handle;
-
-       *volume_handle = 0;
-       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_CONFIG;
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
-       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
-       mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
-       mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
-       mpi_request.Header.PageNumber = 0;
-       mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
-       r = _config_request(ioc, &mpi_request, &mpi_reply,
-           MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
-       if (r)
-               goto out;
-
-       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
-       config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4);
-       config_page = kmalloc(config_page_sz, GFP_KERNEL);
-       if (!config_page) {
-               r = -1;
-               goto out;
-       }
-       config_num = 0xff;
-       while (1) {
-               mpi_request.PageAddress = cpu_to_le32(config_num +
-                   MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM);
-               r = _config_request(ioc, &mpi_request, &mpi_reply,
-                   MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-                   config_page_sz);
-               if (r)
-                       goto out;
-               r = -1;
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-                       goto out;
-               for (i = 0; i < config_page->NumElements; i++) {
-                       element_type = le16_to_cpu(config_page->
-                           ConfigElement[i].ElementFlags) &
-                           MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
-                       if (element_type ==
-                           MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT ||
-                           element_type ==
-                           MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) {
-                               phys_disk_dev_handle =
-                                   le16_to_cpu(config_page->ConfigElement[i].
-                                   PhysDiskDevHandle);
-                               if (phys_disk_dev_handle == pd_handle) {
-                                       *volume_handle =
-                                           le16_to_cpu(config_page->
-                                           ConfigElement[i].VolDevHandle);
-                                       r = 0;
-                                       goto out;
-                               }
-                       } else if (element_type ==
-                           MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) {
-                               *volume_handle = 0;
-                               r = 0;
-                               goto out;
-                       }
-               }
-               config_num = config_page->ConfigNum;
-       }
- out:
-       kfree(config_page);
-       return r;
-}
-
-/**
- * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
- * @ioc: per adapter object
- * @volume_handle: volume handle
- * @wwid: volume wwid
- * Context: sleep.
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
-    u64 *wwid)
-{
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2RaidVolPage1_t raid_vol_pg1;
-
-       *wwid = 0;
-       if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
-           &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
-           volume_handle))) {
-               *wwid = le64_to_cpu(raid_vol_pg1.WWID);
-               return 0;
-       } else
-               return -1;
-}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
deleted file mode 100644 (file)
index 3694b63..0000000
+++ /dev/null
@@ -1,3101 +0,0 @@
-/*
- * Management Module Support for MPT (Message Passing Technology) based
- * controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * 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/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/compat.h>
-#include <linux/poll.h>
-
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include "mpt2sas_base.h"
-#include "mpt2sas_ctl.h"
-
-static DEFINE_MUTEX(_ctl_mutex);
-static struct fasync_struct *async_queue;
-static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
-
-static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
-    u8 *issue_reset);
-
-/**
- * enum block_state - blocking state
- * @NON_BLOCKING: non blocking
- * @BLOCKING: blocking
- *
- * These states are for ioctls that need to wait for a response
- * from firmware, so they probably require sleep.
- */
-enum block_state {
-       NON_BLOCKING,
-       BLOCKING,
-};
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _ctl_sas_device_find_by_handle - sas device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-static struct _sas_device *
-_ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_device *sas_device, *r;
-
-       r = NULL;
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
-               if (sas_device->handle != handle)
-                       continue;
-               r = sas_device;
-               goto out;
-       }
-
- out:
-       return r;
-}
-
-/**
- * _ctl_display_some_debug - debug routine
- * @ioc: per adapter object
- * @smid: system request message index
- * @calling_function_name: string pass from calling function
- * @mpi_reply: reply message frame
- * Context: none.
- *
- * Function for displaying debug info helpful when debugging issues
- * in this module.
- */
-static void
-_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
-{
-       Mpi2ConfigRequest_t *mpi_request;
-       char *desc = NULL;
-
-       if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
-               return;
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       switch (mpi_request->Function) {
-       case MPI2_FUNCTION_SCSI_IO_REQUEST:
-       {
-               Mpi2SCSIIORequest_t *scsi_request =
-                   (Mpi2SCSIIORequest_t *)mpi_request;
-
-               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
-                   "scsi_io, cmd(0x%02x), cdb_len(%d)",
-                   scsi_request->CDB.CDB32[0],
-                   le16_to_cpu(scsi_request->IoFlags) & 0xF);
-               desc = ioc->tmp_string;
-               break;
-       }
-       case MPI2_FUNCTION_SCSI_TASK_MGMT:
-               desc = "task_mgmt";
-               break;
-       case MPI2_FUNCTION_IOC_INIT:
-               desc = "ioc_init";
-               break;
-       case MPI2_FUNCTION_IOC_FACTS:
-               desc = "ioc_facts";
-               break;
-       case MPI2_FUNCTION_CONFIG:
-       {
-               Mpi2ConfigRequest_t *config_request =
-                   (Mpi2ConfigRequest_t *)mpi_request;
-
-               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
-                   "config, type(0x%02x), ext_type(0x%02x), number(%d)",
-                   (config_request->Header.PageType &
-                    MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
-                   config_request->Header.PageNumber);
-               desc = ioc->tmp_string;
-               break;
-       }
-       case MPI2_FUNCTION_PORT_FACTS:
-               desc = "port_facts";
-               break;
-       case MPI2_FUNCTION_PORT_ENABLE:
-               desc = "port_enable";
-               break;
-       case MPI2_FUNCTION_EVENT_NOTIFICATION:
-               desc = "event_notification";
-               break;
-       case MPI2_FUNCTION_FW_DOWNLOAD:
-               desc = "fw_download";
-               break;
-       case MPI2_FUNCTION_FW_UPLOAD:
-               desc = "fw_upload";
-               break;
-       case MPI2_FUNCTION_RAID_ACTION:
-               desc = "raid_action";
-               break;
-       case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
-       {
-               Mpi2SCSIIORequest_t *scsi_request =
-                   (Mpi2SCSIIORequest_t *)mpi_request;
-
-               snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
-                   "raid_pass, cmd(0x%02x), cdb_len(%d)",
-                   scsi_request->CDB.CDB32[0],
-                   le16_to_cpu(scsi_request->IoFlags) & 0xF);
-               desc = ioc->tmp_string;
-               break;
-       }
-       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
-               desc = "sas_iounit_cntl";
-               break;
-       case MPI2_FUNCTION_SATA_PASSTHROUGH:
-               desc = "sata_pass";
-               break;
-       case MPI2_FUNCTION_DIAG_BUFFER_POST:
-               desc = "diag_buffer_post";
-               break;
-       case MPI2_FUNCTION_DIAG_RELEASE:
-               desc = "diag_release";
-               break;
-       case MPI2_FUNCTION_SMP_PASSTHROUGH:
-               desc = "smp_passthrough";
-               break;
-       }
-
-       if (!desc)
-               return;
-
-       printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n",
-           ioc->name, calling_function_name, desc, smid);
-
-       if (!mpi_reply)
-               return;
-
-       if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
-               printk(MPT2SAS_INFO_FMT
-                   "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
-                   le32_to_cpu(mpi_reply->IOCLogInfo));
-
-       if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
-           mpi_request->Function ==
-           MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
-               Mpi2SCSIIOReply_t *scsi_reply =
-                   (Mpi2SCSIIOReply_t *)mpi_reply;
-               struct _sas_device *sas_device = NULL;
-               unsigned long flags;
-
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = _ctl_sas_device_find_by_handle(ioc,
-                   le16_to_cpu(scsi_reply->DevHandle));
-               if (sas_device) {
-                       printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
-                           "phy(%d)\n", ioc->name, (unsigned long long)
-                           sas_device->sas_address, sas_device->phy);
-                       printk(MPT2SAS_WARN_FMT
-                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
-                           ioc->name, sas_device->enclosure_logical_id,
-                           sas_device->slot);
-               }
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
-                       printk(MPT2SAS_INFO_FMT
-                           "\tscsi_state(0x%02x), scsi_status"
-                           "(0x%02x)\n", ioc->name,
-                           scsi_reply->SCSIState,
-                           scsi_reply->SCSIStatus);
-       }
-}
-#endif
-
-/**
- * mpt2sas_ctl_done - ctl module 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: none.
- *
- * The callback handler when using ioc->ctl_cb_idx.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-u8
-mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
-       u32 reply)
-{
-       MPI2DefaultReply_t *mpi_reply;
-       Mpi2SCSIIOReply_t *scsiio_reply;
-       const void *sense_data;
-       u32 sz;
-
-       if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
-               return 1;
-       if (ioc->ctl_cmds.smid != smid)
-               return 1;
-       ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (mpi_reply) {
-               memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
-               ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
-               /* get sense data */
-               if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
-                   mpi_reply->Function ==
-                   MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
-                       scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
-                       if (scsiio_reply->SCSIState &
-                           MPI2_SCSI_STATE_AUTOSENSE_VALID) {
-                               sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
-                                   le32_to_cpu(scsiio_reply->SenseCount));
-                               sense_data = mpt2sas_base_get_sense_buffer(ioc,
-                                   smid);
-                               memcpy(ioc->ctl_cmds.sense, sense_data, sz);
-                       }
-               }
-       }
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
-#endif
-       ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
-       complete(&ioc->ctl_cmds.done);
-       return 1;
-}
-
-/**
- * _ctl_check_event_type - determines when an event needs logging
- * @ioc: per adapter object
- * @event: firmware event
- *
- * The bitmask in ioc->event_type[] indicates which events should be
- * be saved in the driver event_log.  This bitmask is set by application.
- *
- * Returns 1 when event should be captured, or zero means no match.
- */
-static int
-_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event)
-{
-       u16 i;
-       u32 desired_event;
-
-       if (event >= 128 || !event || !ioc->event_log)
-               return 0;
-
-       desired_event = (1 << (event % 32));
-       if (!desired_event)
-               desired_event = 1;
-       i = event / 32;
-       return desired_event & ioc->event_type[i];
-}
-
-/**
- * mpt2sas_ctl_add_to_event_log - add event
- * @ioc: per adapter object
- * @mpi_reply: reply message frame
- *
- * Return nothing.
- */
-void
-mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventNotificationReply_t *mpi_reply)
-{
-       struct MPT2_IOCTL_EVENTS *event_log;
-       u16 event;
-       int i;
-       u32 sz, event_data_sz;
-       u8 send_aen = 0;
-
-       if (!ioc->event_log)
-               return;
-
-       event = le16_to_cpu(mpi_reply->Event);
-
-       if (_ctl_check_event_type(ioc, event)) {
-
-               /* insert entry into circular event_log */
-               i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE;
-               event_log = ioc->event_log;
-               event_log[i].event = event;
-               event_log[i].context = ioc->event_context++;
-
-               event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
-               sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE);
-               memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE);
-               memcpy(event_log[i].data, mpi_reply->EventData, sz);
-               send_aen = 1;
-       }
-
-       /* This aen_event_read_flag flag is set until the
-        * application has read the event log.
-        * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
-        */
-       if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
-           (send_aen && !ioc->aen_event_read_flag)) {
-               ioc->aen_event_read_flag = 1;
-               wake_up_interruptible(&ctl_poll_wait);
-               if (async_queue)
-                       kill_fasync(&async_queue, SIGIO, POLL_IN);
-       }
-}
-
-/**
- * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
- * @ioc: per adapter object
- * @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.
- *
- * Returns void.
- */
-void
-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);
-       if (unlikely(!mpi_reply)) {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-       mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
-       return;
-}
-
-/**
- * _ctl_verify_adapter - validates ioc_number passed from application
- * @ioc: per adapter object
- * @iocpp: The ioc pointer is returned in this.
- *
- * Return (-1) means error, else ioc_number.
- */
-static int
-_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
-{
-       struct MPT2SAS_ADAPTER *ioc;
-       /* global ioc lock to protect controller on list operations */
-       spin_lock(&gioc_lock);
-       list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
-               if (ioc->id != ioc_number)
-                       continue;
-               spin_unlock(&gioc_lock);
-               *iocpp = ioc;
-               return ioc_number;
-       }
-       spin_unlock(&gioc_lock);
-       *iocpp = NULL;
-       return -1;
-}
-
-/**
- * mpt2sas_ctl_reset_handler - reset callback handler (for ctl)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- */
-void
-mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
-       int i;
-       u8 issue_reset;
-
-       switch (reset_phase) {
-       case MPT2_IOC_PRE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
-               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
-                       if (!(ioc->diag_buffer_status[i] &
-                           MPT2_DIAG_BUFFER_IS_REGISTERED))
-                               continue;
-                       if ((ioc->diag_buffer_status[i] &
-                           MPT2_DIAG_BUFFER_IS_RELEASED))
-                               continue;
-                       _ctl_send_release(ioc, i, &issue_reset);
-               }
-               break;
-       case MPT2_IOC_AFTER_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
-               if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->ctl_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
-                       complete(&ioc->ctl_cmds.done);
-               }
-               break;
-       case MPT2_IOC_DONE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
-
-               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
-                       if (!(ioc->diag_buffer_status[i] &
-                           MPT2_DIAG_BUFFER_IS_REGISTERED))
-                               continue;
-                       if ((ioc->diag_buffer_status[i] &
-                           MPT2_DIAG_BUFFER_IS_RELEASED))
-                               continue;
-                       ioc->diag_buffer_status[i] |=
-                           MPT2_DIAG_BUFFER_IS_DIAG_RESET;
-               }
-               break;
-       }
-}
-
-/**
- * _ctl_fasync -
- * @fd -
- * @filep -
- * @mode -
- *
- * Called when application request fasyn callback handler.
- */
-static int
-_ctl_fasync(int fd, struct file *filep, int mode)
-{
-       return fasync_helper(fd, filep, mode, &async_queue);
-}
-
-/**
- * _ctl_poll -
- * @file -
- * @wait -
- *
- */
-static unsigned int
-_ctl_poll(struct file *filep, poll_table *wait)
-{
-       struct MPT2SAS_ADAPTER *ioc;
-
-       poll_wait(filep, &ctl_poll_wait, wait);
-
-       /* global ioc lock to protect controller on list operations */
-       spin_lock(&gioc_lock);
-       list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
-               if (ioc->aen_event_read_flag) {
-                       spin_unlock(&gioc_lock);
-                       return POLLIN | POLLRDNORM;
-               }
-       }
-       spin_unlock(&gioc_lock);
-       return 0;
-}
-
-/**
- * _ctl_set_task_mid - assign an active smid to tm request
- * @ioc: per adapter object
- * @karg - (struct mpt2_ioctl_command)
- * @tm_request - pointer to mf from user space
- *
- * Returns 0 when an smid if found, else fail.
- * during failure, the reply frame is filled.
- */
-static int
-_ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
-    Mpi2SCSITaskManagementRequest_t *tm_request)
-{
-       u8 found = 0;
-       u16 i;
-       u16 handle;
-       struct scsi_cmnd *scmd;
-       struct MPT2SAS_DEVICE *priv_data;
-       unsigned long flags;
-       Mpi2SCSITaskManagementReply_t *tm_reply;
-       u32 sz;
-       u32 lun;
-       char *desc = NULL;
-
-       if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-               desc = "abort_task";
-       else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
-               desc = "query_task";
-       else
-               return 0;
-
-       lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
-
-       handle = le16_to_cpu(tm_request->DevHandle);
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       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)
-                       continue;
-               if (lun != scmd->device->lun)
-                       continue;
-               priv_data = scmd->device->hostdata;
-               if (priv_data->sas_target == NULL)
-                       continue;
-               if (priv_data->sas_target->handle != handle)
-                       continue;
-               tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
-               found = 1;
-       }
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
-       if (!found) {
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
-                   desc, le16_to_cpu(tm_request->DevHandle), lun));
-               tm_reply = ioc->ctl_cmds.reply;
-               tm_reply->DevHandle = tm_request->DevHandle;
-               tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
-               tm_reply->TaskType = tm_request->TaskType;
-               tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
-               tm_reply->VP_ID = tm_request->VP_ID;
-               tm_reply->VF_ID = tm_request->VF_ID;
-               sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
-               if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
-                   sz))
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-               return 1;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-           "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
-           desc, le16_to_cpu(tm_request->DevHandle), lun,
-            le16_to_cpu(tm_request->TaskMID)));
-       return 0;
-}
-
-/**
- * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode
- * @ioc: per adapter object
- * @karg - (struct mpt2_ioctl_command)
- * @mf - pointer to mf in user space
- */
-static long
-_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command karg,
-       void __user *mf)
-{
-       MPI2RequestHeader_t *mpi_request = NULL, *request;
-       MPI2DefaultReply_t *mpi_reply;
-       u32 ioc_state;
-       u16 ioc_status;
-       u16 smid;
-       unsigned long timeout, timeleft;
-       u8 issue_reset;
-       u32 sz;
-       void *psge;
-       void *data_out = NULL;
-       dma_addr_t data_out_dma;
-       size_t data_out_sz = 0;
-       void *data_in = NULL;
-       dma_addr_t data_in_dma;
-       size_t data_in_sz = 0;
-       u32 sgl_flags;
-       long ret;
-       u16 wait_state_count;
-
-       issue_reset = 0;
-
-       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
-                   ioc->name, __func__);
-               ret = -EAGAIN;
-               goto out;
-       }
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       ret = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
-       if (!mpi_request) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for "
-                   "mpi_request\n", ioc->name, __func__);
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       /* Check for overflow and wraparound */
-       if (karg.data_sge_offset * 4 > ioc->request_sz ||
-           karg.data_sge_offset > (UINT_MAX / 4)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* copy in request message frame from user */
-       if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
-                   __func__);
-               ret = -EFAULT;
-               goto out;
-       }
-
-       if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
-               smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
-               if (!smid) {
-                       printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                           ioc->name, __func__);
-                       ret = -EAGAIN;
-                       goto out;
-               }
-       } else {
-
-               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__);
-                       ret = -EAGAIN;
-                       goto out;
-               }
-       }
-
-       ret = 0;
-       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
-       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
-       request = mpt2sas_base_get_msg_frame(ioc, smid);
-       memcpy(request, mpi_request, karg.data_sge_offset*4);
-       ioc->ctl_cmds.smid = smid;
-       data_out_sz = karg.data_out_size;
-       data_in_sz = karg.data_in_size;
-
-       if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
-           mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
-               if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
-                   le16_to_cpu(mpi_request->FunctionDependent1) >
-                   ioc->facts.MaxDevHandle) {
-                       ret = -EINVAL;
-                       mpt2sas_base_free_smid(ioc, smid);
-                       goto out;
-               }
-       }
-
-       /* obtain dma-able memory for data transfer */
-       if (data_out_sz) /* WRITE */ {
-               data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
-                   &data_out_dma);
-               if (!data_out) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret = -ENOMEM;
-                       mpt2sas_base_free_smid(ioc, smid);
-                       goto out;
-               }
-               if (copy_from_user(data_out, karg.data_out_buf_ptr,
-                       data_out_sz)) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret =  -EFAULT;
-                       mpt2sas_base_free_smid(ioc, smid);
-                       goto out;
-               }
-       }
-
-       if (data_in_sz) /* READ */ {
-               data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
-                   &data_in_dma);
-               if (!data_in) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret = -ENOMEM;
-                       mpt2sas_base_free_smid(ioc, smid);
-                       goto out;
-               }
-       }
-
-       /* add scatter gather elements */
-       psge = (void *)request + (karg.data_sge_offset*4);
-
-       if (!data_out_sz && !data_in_sz) {
-               mpt2sas_base_build_zero_len_sge(ioc, psge);
-       } else if (data_out_sz && data_in_sz) {
-               /* WRITE sgel first */
-               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-                   MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
-               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   data_out_sz, data_out_dma);
-
-               /* incr sgel */
-               psge += ioc->sge_size;
-
-               /* READ sgel last */
-               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-                   MPI2_SGE_FLAGS_END_OF_LIST);
-               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   data_in_sz, data_in_dma);
-       } else if (data_out_sz) /* WRITE */ {
-               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-                   MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
-               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   data_out_sz, data_out_dma);
-       } else if (data_in_sz) /* READ */ {
-               sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-                   MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-                   MPI2_SGE_FLAGS_END_OF_LIST);
-               sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   data_in_sz, data_in_dma);
-       }
-
-       /* send command to firmware */
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
-#endif
-
-       init_completion(&ioc->ctl_cmds.done);
-       switch (mpi_request->Function) {
-       case MPI2_FUNCTION_SCSI_IO_REQUEST:
-       case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
-       {
-               Mpi2SCSIIORequest_t *scsiio_request =
-                   (Mpi2SCSIIORequest_t *)request;
-               scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
-               scsiio_request->SenseBufferLowAddress =
-                   mpt2sas_base_get_sense_buffer_dma(ioc, smid);
-               memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
-               if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
-                       mpt2sas_base_put_smid_scsi_io(ioc, smid,
-                           le16_to_cpu(mpi_request->FunctionDependent1));
-               else
-                       mpt2sas_base_put_smid_default(ioc, smid);
-               break;
-       }
-       case MPI2_FUNCTION_SCSI_TASK_MGMT:
-       {
-               Mpi2SCSITaskManagementRequest_t *tm_request =
-                   (Mpi2SCSITaskManagementRequest_t *)request;
-
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
-                   "handle(0x%04x), task_type(0x%02x)\n", ioc->name,
-                   le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
-
-               if (tm_request->TaskType ==
-                   MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
-                   tm_request->TaskType ==
-                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
-                       if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
-                               mpt2sas_base_free_smid(ioc, smid);
-                               goto out;
-                       }
-               }
-
-               mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
-                   tm_request->DevHandle));
-               mpt2sas_base_put_smid_hi_priority(ioc, smid);
-               break;
-       }
-       case MPI2_FUNCTION_SMP_PASSTHROUGH:
-       {
-               Mpi2SmpPassthroughRequest_t *smp_request =
-                   (Mpi2SmpPassthroughRequest_t *)mpi_request;
-               u8 *data;
-
-               /* ioc determines which port to use */
-               smp_request->PhysicalPort = 0xFF;
-               if (smp_request->PassthroughFlags &
-                   MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
-                       data = (u8 *)&smp_request->SGL;
-               else {
-                       if (unlikely(data_out == NULL)) {
-                               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                                   __FILE__, __LINE__, __func__);
-                               mpt2sas_base_free_smid(ioc, smid);
-                               ret = -EINVAL;
-                               goto out;
-                       }
-                       data = data_out;
-               }
-
-               if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
-                       ioc->ioc_link_reset_in_progress = 1;
-                       ioc->ignore_loginfos = 1;
-               }
-               mpt2sas_base_put_smid_default(ioc, smid);
-               break;
-       }
-       case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
-       {
-               Mpi2SasIoUnitControlRequest_t *sasiounit_request =
-                   (Mpi2SasIoUnitControlRequest_t *)mpi_request;
-
-               if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
-                   || sasiounit_request->Operation ==
-                   MPI2_SAS_OP_PHY_LINK_RESET) {
-                       ioc->ioc_link_reset_in_progress = 1;
-                       ioc->ignore_loginfos = 1;
-               }
-               mpt2sas_base_put_smid_default(ioc, smid);
-               break;
-       }
-       default:
-               mpt2sas_base_put_smid_default(ioc, smid);
-               break;
-       }
-
-       if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT)
-               timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
-       else
-               timeout = karg.timeout;
-       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
-           timeout*HZ);
-       if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
-               Mpi2SCSITaskManagementRequest_t *tm_request =
-                   (Mpi2SCSITaskManagementRequest_t *)mpi_request;
-               mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
-                   tm_request->DevHandle));
-       } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
-           mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
-               ioc->ioc_link_reset_in_progress) {
-               ioc->ioc_link_reset_in_progress = 0;
-               ioc->ignore_loginfos = 0;
-       }
-       if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
-                   __func__);
-               _debug_dump_mf(mpi_request, karg.data_sge_offset);
-               if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       mpi_reply = ioc->ctl_cmds.reply;
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
-           (ioc->logging_level & MPT_DEBUG_TM)) {
-               Mpi2SCSITaskManagementReply_t *tm_reply =
-                   (Mpi2SCSITaskManagementReply_t *)mpi_reply;
-
-               printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
-                   "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
-                   "TerminationCount(0x%08x)\n", ioc->name,
-                   le16_to_cpu(tm_reply->IOCStatus),
-                   le32_to_cpu(tm_reply->IOCLogInfo),
-                   le32_to_cpu(tm_reply->TerminationCount));
-       }
-#endif
-       /* copy out xdata to user */
-       if (data_in_sz) {
-               if (copy_to_user(karg.data_in_buf_ptr, data_in,
-                   data_in_sz)) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret = -ENODATA;
-                       goto out;
-               }
-       }
-
-       /* copy out reply message frame to user */
-       if (karg.max_reply_bytes) {
-               sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
-               if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
-                   sz)) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret = -ENODATA;
-                       goto out;
-               }
-       }
-
-       /* copy out sense to user */
-       if (karg.max_sense_bytes && (mpi_request->Function ==
-           MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
-           MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
-               sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
-               if (copy_to_user(karg.sense_data_ptr,
-                       ioc->ctl_cmds.sense, sz)) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                           __LINE__, __func__);
-                       ret = -ENODATA;
-                       goto out;
-               }
-       }
-
- issue_host_reset:
-       if (issue_reset) {
-               ret = -ENODATA;
-               if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
-                   mpi_request->Function ==
-                   MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
-                   mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) {
-                       printk(MPT2SAS_INFO_FMT "issue target reset: handle "
-                           "= (0x%04x)\n", ioc->name,
-                           le16_to_cpu(mpi_request->FunctionDependent1));
-                       mpt2sas_halt_firmware(ioc);
-                       mpt2sas_scsih_issue_tm(ioc,
-                           le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
-                           0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10,
-                           TM_MUTEX_ON);
-                       ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-               } else
-                       mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                           FORCE_BIG_HAMMER);
-       }
-
- out:
-
-       /* free memory associated with sg buffers */
-       if (data_in)
-               pci_free_consistent(ioc->pdev, data_in_sz, data_in,
-                   data_in_dma);
-
-       if (data_out)
-               pci_free_consistent(ioc->pdev, data_out_sz, data_out,
-                   data_out_dma);
-
-       kfree(mpi_request);
-       ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
-       return ret;
-}
-
-/**
- * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_getiocinfo(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_iocinfo karg;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       memset(&karg, 0 , sizeof(karg));
-       if (ioc->is_warpdrive)
-               karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
-       else
-               karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
-       if (ioc->pfacts)
-               karg.port_number = ioc->pfacts[0].PortNumber;
-       karg.hw_rev = ioc->pdev->revision;
-       karg.pci_id = ioc->pdev->device;
-       karg.subsystem_device = ioc->pdev->subsystem_device;
-       karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
-       karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
-       karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
-       karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
-       karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
-       karg.firmware_version = ioc->facts.FWVersion.Word;
-       strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME);
-       strcat(karg.driver_version, "-");
-       strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
-       karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
-
-       if (copy_to_user(arg, &karg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-       return 0;
-}
-
-/**
- * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventquery(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_eventquery karg;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
-       memcpy(karg.event_types, ioc->event_type,
-           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
-
-       if (copy_to_user(arg, &karg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-       return 0;
-}
-
-/**
- * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventenable(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_eventenable karg;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       if (ioc->event_log)
-               return 0;
-       memcpy(ioc->event_type, karg.event_types,
-           MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
-       mpt2sas_base_validate_event_type(ioc, ioc->event_type);
-
-       /* initialize event_log */
-       ioc->event_context = 0;
-       ioc->aen_event_read_flag = 0;
-       ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE,
-           sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL);
-       if (!ioc->event_log) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/**
- * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_eventreport(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_eventreport karg;
-       u32 number_bytes, max_events, max;
-       struct mpt2_ioctl_eventreport __user *uarg = arg;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       number_bytes = karg.hdr.max_data_size -
-           sizeof(struct mpt2_ioctl_header);
-       max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS);
-       max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events);
-
-       /* If fewer than 1 event is requested, there must have
-        * been some type of error.
-        */
-       if (!max || !ioc->event_log)
-               return -ENODATA;
-
-       number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS);
-       if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       /* reset flag so SIGIO can restart */
-       ioc->aen_event_read_flag = 0;
-       return 0;
-}
-
-/**
- * _ctl_do_reset - main handler for MPT2HARDRESET opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_do_reset(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_diag_reset karg;
-       int retval;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery ||
-               ioc->is_driver_loading)
-               return -EAGAIN;
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
-           __func__));
-
-       retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-           FORCE_BIG_HAMMER);
-       printk(MPT2SAS_INFO_FMT "host reset: %s\n",
-           ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
-       return 0;
-}
-
-/**
- * _ctl_btdh_search_sas_device - searching for sas device
- * @ioc: per adapter object
- * @btdh: btdh ioctl payload
- */
-static int
-_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc,
-    struct mpt2_ioctl_btdh_mapping *btdh)
-{
-       struct _sas_device *sas_device;
-       unsigned long flags;
-       int rc = 0;
-
-       if (list_empty(&ioc->sas_device_list))
-               return rc;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
-               if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
-                   btdh->handle == sas_device->handle) {
-                       btdh->bus = sas_device->channel;
-                       btdh->id = sas_device->id;
-                       rc = 1;
-                       goto out;
-               } else if (btdh->bus == sas_device->channel && btdh->id ==
-                   sas_device->id && btdh->handle == 0xFFFF) {
-                       btdh->handle = sas_device->handle;
-                       rc = 1;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       return rc;
-}
-
-/**
- * _ctl_btdh_search_raid_device - searching for raid device
- * @ioc: per adapter object
- * @btdh: btdh ioctl payload
- */
-static int
-_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
-    struct mpt2_ioctl_btdh_mapping *btdh)
-{
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       int rc = 0;
-
-       if (list_empty(&ioc->raid_device_list))
-               return rc;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
-               if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
-                   btdh->handle == raid_device->handle) {
-                       btdh->bus = raid_device->channel;
-                       btdh->id = raid_device->id;
-                       rc = 1;
-                       goto out;
-               } else if (btdh->bus == raid_device->channel && btdh->id ==
-                   raid_device->id && btdh->handle == 0xFFFF) {
-                       btdh->handle = raid_device->handle;
-                       rc = 1;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       return rc;
-}
-
-/**
- * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_btdh_mapping(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_ioctl_btdh_mapping karg;
-       int rc;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       rc = _ctl_btdh_search_sas_device(ioc, &karg);
-       if (!rc)
-               _ctl_btdh_search_raid_device(ioc, &karg);
-
-       if (copy_to_user(arg, &karg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-       return 0;
-}
-
-/**
- * _ctl_diag_capability - return diag buffer capability
- * @ioc: per adapter object
- * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
- *
- * returns 1 when diag buffer support is enabled in firmware
- */
-static u8
-_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
-{
-       u8 rc = 0;
-
-       switch (buffer_type) {
-       case MPI2_DIAG_BUF_TYPE_TRACE:
-               if (ioc->facts.IOCCapabilities &
-                   MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
-                       rc = 1;
-               break;
-       case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
-               if (ioc->facts.IOCCapabilities &
-                   MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
-                       rc = 1;
-               break;
-       case MPI2_DIAG_BUF_TYPE_EXTENDED:
-               if (ioc->facts.IOCCapabilities &
-                   MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
-                       rc = 1;
-       }
-
-       return rc;
-}
-
-/**
- * _ctl_diag_register_2 - wrapper for registering diag buffer support
- * @ioc: per adapter object
- * @diag_register: the diag_register struct passed in from user space
- *
- */
-static long
-_ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
-    struct mpt2_diag_register *diag_register)
-{
-       int rc, i;
-       void *request_data = NULL;
-       dma_addr_t request_data_dma;
-       u32 request_data_sz = 0;
-       Mpi2DiagBufferPostRequest_t *mpi_request;
-       Mpi2DiagBufferPostReply_t *mpi_reply;
-       u8 buffer_type;
-       unsigned long timeleft;
-       u16 smid;
-       u16 ioc_status;
-       u8 issue_reset = 0;
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       buffer_type = diag_register->buffer_type;
-       if (!_ctl_diag_capability(ioc, buffer_type)) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -EPERM;
-       }
-
-       if (ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) {
-               printk(MPT2SAS_ERR_FMT "%s: already has a registered "
-                   "buffer for buffer_type(0x%02x)\n", ioc->name, __func__,
-                   buffer_type);
-               return -EINVAL;
-       }
-
-       if (diag_register->requested_buffer_size % 4)  {
-               printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
-                   "is not 4 byte aligned\n", ioc->name, __func__);
-               return -EINVAL;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       rc = 0;
-       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
-       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->ctl_cmds.smid = smid;
-
-       request_data = ioc->diag_buffer[buffer_type];
-       request_data_sz = diag_register->requested_buffer_size;
-       ioc->unique_id[buffer_type] = diag_register->unique_id;
-       ioc->diag_buffer_status[buffer_type] = 0;
-       memcpy(ioc->product_specific[buffer_type],
-           diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS);
-       ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
-
-       if (request_data) {
-               request_data_dma = ioc->diag_buffer_dma[buffer_type];
-               if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
-                       pci_free_consistent(ioc->pdev,
-                           ioc->diag_buffer_sz[buffer_type],
-                           request_data, request_data_dma);
-                       request_data = NULL;
-               }
-       }
-
-       if (request_data == NULL) {
-               ioc->diag_buffer_sz[buffer_type] = 0;
-               ioc->diag_buffer_dma[buffer_type] = 0;
-               request_data = pci_alloc_consistent(
-                       ioc->pdev, request_data_sz, &request_data_dma);
-               if (request_data == NULL) {
-                       printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"
-                           " for diag buffers, requested size(%d)\n",
-                           ioc->name, __func__, request_data_sz);
-                       mpt2sas_base_free_smid(ioc, smid);
-                       return -ENOMEM;
-               }
-               ioc->diag_buffer[buffer_type] = request_data;
-               ioc->diag_buffer_sz[buffer_type] = request_data_sz;
-               ioc->diag_buffer_dma[buffer_type] = request_data_dma;
-       }
-
-       mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
-       mpi_request->BufferType = diag_register->buffer_type;
-       mpi_request->Flags = cpu_to_le32(diag_register->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_INFO_FMT "%s: diag_buffer(0x%p), "
-           "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
-           (unsigned long long)request_data_dma,
-           le32_to_cpu(mpi_request->BufferLength)));
-
-       for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
-               mpi_request->ProductSpecific[i] =
-                       cpu_to_le32(ioc->product_specific[buffer_type][i]);
-
-       init_completion(&ioc->ctl_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
-           MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
-       if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
-                   __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2DiagBufferPostRequest_t)/4);
-               if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       /* process the completed Reply Message Frame */
-       if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
-                   ioc->name, __func__);
-               rc = -EFAULT;
-               goto out;
-       }
-
-       mpi_reply = ioc->ctl_cmds.reply;
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
-               ioc->diag_buffer_status[buffer_type] |=
-                       MPT2_DIAG_BUFFER_IS_REGISTERED;
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
-                   ioc->name, __func__));
-       } else {
-               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
-                   "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
-               rc = -EFAULT;
-       }
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-
- out:
-
-       if (rc && request_data)
-               pci_free_consistent(ioc->pdev, request_data_sz,
-                   request_data, request_data_dma);
-
-       ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
-       return rc;
-}
-
-/**
- * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time
- * @ioc: per adapter object
- * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
- *
- * This is called when command line option diag_buffer_enable is enabled
- * at driver load time.
- */
-void
-mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
-{
-       struct mpt2_diag_register diag_register;
-
-       memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
-
-       if (bits_to_register & 1) {
-               printk(MPT2SAS_INFO_FMT "registering trace buffer support\n",
-                   ioc->name);
-               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
-               /* register for 1MB buffers  */
-               diag_register.requested_buffer_size = (1024 * 1024);
-               diag_register.unique_id = 0x7075900;
-               _ctl_diag_register_2(ioc,  &diag_register);
-       }
-
-       if (bits_to_register & 2) {
-               printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n",
-                   ioc->name);
-               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
-               /* register for 2MB buffers  */
-               diag_register.requested_buffer_size = 2 * (1024 * 1024);
-               diag_register.unique_id = 0x7075901;
-               _ctl_diag_register_2(ioc,  &diag_register);
-       }
-
-       if (bits_to_register & 4) {
-               printk(MPT2SAS_INFO_FMT "registering extended buffer support\n",
-                   ioc->name);
-               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
-               /* register for 2MB buffers  */
-               diag_register.requested_buffer_size = 2 * (1024 * 1024);
-               diag_register.unique_id = 0x7075901;
-               _ctl_diag_register_2(ioc,  &diag_register);
-       }
-}
-
-/**
- * _ctl_diag_register - application register with driver
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * This will allow the driver to setup any required buffers that will be
- * needed by firmware to communicate with the driver.
- */
-static long
-_ctl_diag_register(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_diag_register karg;
-       long rc;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       rc = _ctl_diag_register_2(ioc, &karg);
-       return rc;
-}
-
-/**
- * _ctl_diag_unregister - application unregister with driver
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * This will allow the driver to cleanup any memory allocated for diag
- * messages and to free up any resources.
- */
-static long
-_ctl_diag_unregister(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_diag_unregister karg;
-       void *request_data;
-       dma_addr_t request_data_dma;
-       u32 request_data_sz;
-       u8 buffer_type;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       buffer_type = karg.unique_id & 0x000000ff;
-       if (!_ctl_diag_capability(ioc, buffer_type)) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -EPERM;
-       }
-
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
-                   "registered\n", ioc->name, __func__, buffer_type);
-               return -EINVAL;
-       }
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been "
-                   "released\n", ioc->name, __func__, buffer_type);
-               return -EINVAL;
-       }
-
-       if (karg.unique_id != ioc->unique_id[buffer_type]) {
-               printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
-                   "registered\n", ioc->name, __func__, karg.unique_id);
-               return -EINVAL;
-       }
-
-       request_data = ioc->diag_buffer[buffer_type];
-       if (!request_data) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -ENOMEM;
-       }
-
-       request_data_sz = ioc->diag_buffer_sz[buffer_type];
-       request_data_dma = ioc->diag_buffer_dma[buffer_type];
-       pci_free_consistent(ioc->pdev, request_data_sz,
-           request_data, request_data_dma);
-       ioc->diag_buffer[buffer_type] = NULL;
-       ioc->diag_buffer_status[buffer_type] = 0;
-       return 0;
-}
-
-/**
- * _ctl_diag_query - query relevant info associated with diag buffers
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- *
- * The application will send only buffer_type and unique_id.  Driver will
- * inspect unique_id first, if valid, fill in all the info.  If unique_id is
- * 0x00, the driver will return info specified by Buffer Type.
- */
-static long
-_ctl_diag_query(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_diag_query karg;
-       void *request_data;
-       int i;
-       u8 buffer_type;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       karg.application_flags = 0;
-       buffer_type = karg.buffer_type;
-
-       if (!_ctl_diag_capability(ioc, buffer_type)) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -EPERM;
-       }
-
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
-                   "registered\n", ioc->name, __func__, buffer_type);
-               return -EINVAL;
-       }
-
-       if (karg.unique_id & 0xffffff00) {
-               if (karg.unique_id != ioc->unique_id[buffer_type]) {
-                       printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
-                           "registered\n", ioc->name, __func__,
-                           karg.unique_id);
-                       return -EINVAL;
-               }
-       }
-
-       request_data = ioc->diag_buffer[buffer_type];
-       if (!request_data) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -ENOMEM;
-       }
-
-       if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED)
-               karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
-                   MPT2_APP_FLAGS_BUFFER_VALID);
-       else
-               karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
-                   MPT2_APP_FLAGS_BUFFER_VALID |
-                   MPT2_APP_FLAGS_FW_BUFFER_ACCESS);
-
-       for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
-               karg.product_specific[i] =
-                   ioc->product_specific[buffer_type][i];
-
-       karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
-       karg.driver_added_buffer_size = 0;
-       karg.unique_id = ioc->unique_id[buffer_type];
-       karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
-
-       if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) {
-               printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query "
-                   "data @ %p\n", ioc->name, __func__, arg);
-               return -EFAULT;
-       }
-       return 0;
-}
-
-/**
- * _ctl_send_release - Diag Release Message
- * @ioc: per adapter object
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @issue_reset - specifies whether host reset is required.
- *
- */
-static int
-_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
-{
-       Mpi2DiagReleaseRequest_t *mpi_request;
-       Mpi2DiagReleaseReply_t *mpi_reply;
-       u16 smid;
-       u16 ioc_status;
-       u32 ioc_state;
-       int rc;
-       unsigned long timeleft;
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       rc = 0;
-       *issue_reset = 0;
-
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "skipping due to FAULT state\n", ioc->name,
-                   __func__));
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
-       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->ctl_cmds.smid = smid;
-
-       mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
-       mpi_request->BufferType = buffer_type;
-       mpi_request->VF_ID = 0; /* TODO */
-       mpi_request->VP_ID = 0;
-
-       init_completion(&ioc->ctl_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
-           MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
-       if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
-                   __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2DiagReleaseRequest_t)/4);
-               if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
-                       *issue_reset = 1;
-               rc = -EFAULT;
-               goto out;
-       }
-
-       /* process the completed Reply Message Frame */
-       if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
-                   ioc->name, __func__);
-               rc = -EFAULT;
-               goto out;
-       }
-
-       mpi_reply = ioc->ctl_cmds.reply;
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
-               ioc->diag_buffer_status[buffer_type] |=
-                   MPT2_DIAG_BUFFER_IS_RELEASED;
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
-                   ioc->name, __func__));
-       } else {
-               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
-                   "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
-               rc = -EFAULT;
-       }
-
- out:
-       ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
-       return rc;
-}
-
-/**
- * _ctl_diag_release - request to send Diag Release Message to firmware
- * @arg - user space buffer containing ioctl content
- *
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
- */
-static long
-_ctl_diag_release(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_diag_release karg;
-       void *request_data;
-       int rc;
-       u8 buffer_type;
-       u8 issue_reset = 0;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       buffer_type = karg.unique_id & 0x000000ff;
-       if (!_ctl_diag_capability(ioc, buffer_type)) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -EPERM;
-       }
-
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
-                   "registered\n", ioc->name, __func__, buffer_type);
-               return -EINVAL;
-       }
-
-       if (karg.unique_id != ioc->unique_id[buffer_type]) {
-               printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
-                   "registered\n", ioc->name, __func__, karg.unique_id);
-               return -EINVAL;
-       }
-
-       if (ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_RELEASED) {
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
-                   "is already released\n", ioc->name, __func__,
-                   buffer_type);
-               return 0;
-       }
-
-       request_data = ioc->diag_buffer[buffer_type];
-
-       if (!request_data) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -ENOMEM;
-       }
-
-       /* buffers were released by due to host reset */
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
-               ioc->diag_buffer_status[buffer_type] |=
-                   MPT2_DIAG_BUFFER_IS_RELEASED;
-               ioc->diag_buffer_status[buffer_type] &=
-                   ~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
-               printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
-                   "was released due to host reset\n", ioc->name, __func__,
-                   buffer_type);
-               return 0;
-       }
-
-       rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
-
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-
-       return rc;
-}
-
-/**
- * _ctl_diag_read_buffer - request for copy of the diag buffer
- * @ioc: per adapter object
- * @arg - user space buffer containing ioctl content
- */
-static long
-_ctl_diag_read_buffer(struct MPT2SAS_ADAPTER *ioc, void __user *arg)
-{
-       struct mpt2_diag_read_buffer karg;
-       struct mpt2_diag_read_buffer __user *uarg = arg;
-       void *request_data, *diag_data;
-       Mpi2DiagBufferPostRequest_t *mpi_request;
-       Mpi2DiagBufferPostReply_t *mpi_reply;
-       int rc, i;
-       u8 buffer_type;
-       unsigned long timeleft, request_size, copy_size;
-       u16 smid;
-       u16 ioc_status;
-       u8 issue_reset = 0;
-
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
-           __func__));
-
-       buffer_type = karg.unique_id & 0x000000ff;
-       if (!_ctl_diag_capability(ioc, buffer_type)) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -EPERM;
-       }
-
-       if (karg.unique_id != ioc->unique_id[buffer_type]) {
-               printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
-                   "registered\n", ioc->name, __func__, karg.unique_id);
-               return -EINVAL;
-       }
-
-       request_data = ioc->diag_buffer[buffer_type];
-       if (!request_data) {
-               printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
-                   "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
-               return -ENOMEM;
-       }
-
-       request_size = ioc->diag_buffer_sz[buffer_type];
-
-       if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
-               printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
-                   "or bytes_to_read are not 4 byte aligned\n", ioc->name,
-                   __func__);
-               return -EINVAL;
-       }
-
-       if (karg.starting_offset > request_size)
-               return -EINVAL;
-
-       diag_data = (void *)(request_data + karg.starting_offset);
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
-           "offset(%d), sz(%d)\n", ioc->name, __func__,
-           diag_data, karg.starting_offset, karg.bytes_to_read));
-
-       /* Truncate data on requests that are too large */
-       if ((diag_data + karg.bytes_to_read < diag_data) ||
-           (diag_data + karg.bytes_to_read > request_data + request_size))
-               copy_size = request_size - karg.starting_offset;
-       else
-               copy_size = karg.bytes_to_read;
-
-       if (copy_to_user((void __user *)uarg->diagnostic_data,
-           diag_data, copy_size)) {
-               printk(MPT2SAS_ERR_FMT "%s: Unable to write "
-                   "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
-                   __func__, diag_data);
-               return -EFAULT;
-       }
-
-       if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
-               return 0;
-
-       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister "
-               "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
-       if ((ioc->diag_buffer_status[buffer_type] &
-           MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "buffer_type(0x%02x) is still registered\n", ioc->name,
-                    __func__, buffer_type));
-               return 0;
-       }
-       /* Get a free request frame and save the message context.
-       */
-
-       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       rc = 0;
-       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
-       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->ctl_cmds.smid = smid;
-
-       mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
-       mpi_request->BufferType = buffer_type;
-       mpi_request->BufferLength =
-           cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
-       mpi_request->BufferAddress =
-           cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
-       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;
-
-       init_completion(&ioc->ctl_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
-           MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
-
-       if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
-                   __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2DiagBufferPostRequest_t)/4);
-               if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       /* process the completed Reply Message Frame */
-       if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
-                   ioc->name, __func__);
-               rc = -EFAULT;
-               goto out;
-       }
-
-       mpi_reply = ioc->ctl_cmds.reply;
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
-
-       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
-               ioc->diag_buffer_status[buffer_type] |=
-                   MPT2_DIAG_BUFFER_IS_REGISTERED;
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
-                   ioc->name, __func__));
-       } else {
-               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
-                   "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
-               rc = -EFAULT;
-       }
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-
- out:
-
-       ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
-       return rc;
-}
-
-
-#ifdef CONFIG_COMPAT
-/**
- * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
- * @ioc: per adapter object
- * @cmd - ioctl opcode
- * @arg - (struct mpt2_ioctl_command32)
- *
- * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
- */
-static long
-_ctl_compat_mpt_command(struct MPT2SAS_ADAPTER *ioc, unsigned cmd,
-       void __user *arg)
-{
-       struct mpt2_ioctl_command32 karg32;
-       struct mpt2_ioctl_command32 __user *uarg;
-       struct mpt2_ioctl_command karg;
-
-       if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
-               return -EINVAL;
-
-       uarg = (struct mpt2_ioctl_command32 __user *) arg;
-
-       if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
-       karg.hdr.ioc_number = karg32.hdr.ioc_number;
-       karg.hdr.port_number = karg32.hdr.port_number;
-       karg.hdr.max_data_size = karg32.hdr.max_data_size;
-       karg.timeout = karg32.timeout;
-       karg.max_reply_bytes = karg32.max_reply_bytes;
-       karg.data_in_size = karg32.data_in_size;
-       karg.data_out_size = karg32.data_out_size;
-       karg.max_sense_bytes = karg32.max_sense_bytes;
-       karg.data_sge_offset = karg32.data_sge_offset;
-       karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr);
-       karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr);
-       karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr);
-       karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr);
-       return _ctl_do_mpt_command(ioc, karg, &uarg->mf);
-}
-#endif
-
-/**
- * _ctl_ioctl_main - main ioctl entry point
- * @file - (struct file)
- * @cmd - ioctl opcode
- * @arg -
- * compat - handles 32 bit applications in 64bit os
- */
-static long
-_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
-       u8 compat)
-{
-       struct MPT2SAS_ADAPTER *ioc;
-       struct mpt2_ioctl_header ioctl_header;
-       enum block_state state;
-       long ret = -EINVAL;
-
-       /* get IOCTL header */
-       if (copy_from_user(&ioctl_header, (char __user *)arg,
-           sizeof(struct mpt2_ioctl_header))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-
-       if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
-               return -ENODEV;
-       /* pci_access_mutex lock acquired by ioctl path */
-       mutex_lock(&ioc->pci_access_mutex);
-       if (ioc->shost_recovery || ioc->pci_error_recovery ||
-               ioc->is_driver_loading || ioc->remove_host) {
-               ret = -EAGAIN;
-               goto out_unlock_pciaccess;
-       }
-
-       state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
-       if (state == NON_BLOCKING) {
-               if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
-                       ret = -EAGAIN;
-                       goto out_unlock_pciaccess;
-               }
-       } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
-               ret = -ERESTARTSYS;
-               goto out_unlock_pciaccess;
-       }
-
-       switch (cmd) {
-       case MPT2IOCINFO:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
-                       ret = _ctl_getiocinfo(ioc, arg);
-               break;
-#ifdef CONFIG_COMPAT
-       case MPT2COMMAND32:
-#endif
-       case MPT2COMMAND:
-       {
-               struct mpt2_ioctl_command __user *uarg;
-               struct mpt2_ioctl_command karg;
-#ifdef CONFIG_COMPAT
-               if (compat) {
-                       ret = _ctl_compat_mpt_command(ioc, cmd, arg);
-                       break;
-               }
-#endif
-               if (copy_from_user(&karg, arg, sizeof(karg))) {
-                       printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                           __FILE__, __LINE__, __func__);
-                       ret = -EFAULT;
-                       break;
-               }
-
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
-                       uarg = arg;
-                       ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf);
-               }
-               break;
-       }
-       case MPT2EVENTQUERY:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
-                       ret = _ctl_eventquery(ioc, arg);
-               break;
-       case MPT2EVENTENABLE:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
-                       ret = _ctl_eventenable(ioc, arg);
-               break;
-       case MPT2EVENTREPORT:
-               ret = _ctl_eventreport(ioc, arg);
-               break;
-       case MPT2HARDRESET:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
-                       ret = _ctl_do_reset(ioc, arg);
-               break;
-       case MPT2BTDHMAPPING:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
-                       ret = _ctl_btdh_mapping(ioc, arg);
-               break;
-       case MPT2DIAGREGISTER:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
-                       ret = _ctl_diag_register(ioc, arg);
-               break;
-       case MPT2DIAGUNREGISTER:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
-                       ret = _ctl_diag_unregister(ioc, arg);
-               break;
-       case MPT2DIAGQUERY:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
-                       ret = _ctl_diag_query(ioc, arg);
-               break;
-       case MPT2DIAGRELEASE:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
-                       ret = _ctl_diag_release(ioc, arg);
-               break;
-       case MPT2DIAGREADBUFFER:
-               if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
-                       ret = _ctl_diag_read_buffer(ioc, arg);
-               break;
-       default:
-
-               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
-               break;
-       }
-
-       mutex_unlock(&ioc->ctl_cmds.mutex);
-out_unlock_pciaccess:
-       mutex_unlock(&ioc->pci_access_mutex);
-       return ret;
-}
-
-/**
- * _ctl_ioctl - main ioctl entry point (unlocked)
- * @file - (struct file)
- * @cmd - ioctl opcode
- * @arg -
- */
-static long
-_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       long ret;
-
-       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
-       return ret;
-}
-#ifdef CONFIG_COMPAT
-/**
- * _ctl_ioctl_compat - main ioctl entry point (compat)
- * @file -
- * @cmd -
- * @arg -
- *
- * This routine handles 32 bit applications in 64bit os.
- */
-static long
-_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
-{
-       long ret;
-
-       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
-       return ret;
-}
-#endif
-
-/* scsi host attributes */
-
-/**
- * _ctl_version_fw_show - firmware version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
-           (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
-           (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
-           (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
-           ioc->facts.FWVersion.Word & 0x000000FF);
-}
-static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
-
-/**
- * _ctl_version_bios_show - bios version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
-
-       return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
-           (version & 0xFF000000) >> 24,
-           (version & 0x00FF0000) >> 16,
-           (version & 0x0000FF00) >> 8,
-           version & 0x000000FF);
-}
-static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
-
-/**
- * _ctl_version_mpi_show - MPI (message passing interface) version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
-           ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
-}
-static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
-
-/**
- * _ctl_version_product_show - product name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
-}
-static DEVICE_ATTR(version_product, S_IRUGO,
-   _ctl_version_product_show, NULL);
-
-/**
- * _ctl_version_nvdata_persistent_show - ndvata persistent version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_nvdata_persistent_show(struct device *cdev,
-    struct device_attribute *attr, char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%08xh\n",
-           le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
-}
-static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
-    _ctl_version_nvdata_persistent_show, NULL);
-
-/**
- * _ctl_version_nvdata_default_show - nvdata default version
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_version_nvdata_default_show(struct device *cdev,
-    struct device_attribute *attr, char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%08xh\n",
-           le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
-}
-static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
-    _ctl_version_nvdata_default_show, NULL);
-
-/**
- * _ctl_board_name_show - board name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
-}
-static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
-
-/**
- * _ctl_board_assembly_show - board assembly name
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
-}
-static DEVICE_ATTR(board_assembly, S_IRUGO,
-    _ctl_board_assembly_show, NULL);
-
-/**
- * _ctl_board_tracer_show - board tracer number
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
-}
-static DEVICE_ATTR(board_tracer, S_IRUGO,
-    _ctl_board_tracer_show, NULL);
-
-/**
- * _ctl_io_delay_show - io missing delay
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is for firmware implemention for deboucing device
- * removal events.
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
-}
-static DEVICE_ATTR(io_delay, S_IRUGO,
-    _ctl_io_delay_show, NULL);
-
-/**
- * _ctl_device_delay_show - device missing delay
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is for firmware implemention for deboucing device
- * removal events.
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
-}
-static DEVICE_ATTR(device_delay, S_IRUGO,
-    _ctl_device_delay_show, NULL);
-
-/**
- * _ctl_fw_queue_depth_show - global credits
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is firmware queue depth limit
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
-}
-static DEVICE_ATTR(fw_queue_depth, S_IRUGO,
-    _ctl_fw_queue_depth_show, NULL);
-
-/**
- * _ctl_sas_address_show - sas address
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the controller sas address
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
-           (unsigned long long)ioc->sas_hba.sas_address);
-}
-static DEVICE_ATTR(host_sas_address, S_IRUGO,
-    _ctl_host_sas_address_show, NULL);
-
-/**
- * _ctl_logging_level_show - logging level
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- */
-static ssize_t
-_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
-}
-static ssize_t
-_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
-    const char *buf, size_t count)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       int val = 0;
-
-       if (sscanf(buf, "%x", &val) != 1)
-               return -EINVAL;
-
-       ioc->logging_level = val;
-       printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name,
-           ioc->logging_level);
-       return strlen(buf);
-}
-static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
-    _ctl_logging_level_show, _ctl_logging_level_store);
-
-/* device attributes */
-/*
- * _ctl_fwfault_debug_show - show/store fwfault_debug
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * mpt2sas_fwfault_debug is command line option
- * A sysfs 'read/write' shost attribute.
- */
-static ssize_t
-_ctl_fwfault_debug_show(struct device *cdev,
-    struct device_attribute *attr, char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug);
-}
-static ssize_t
-_ctl_fwfault_debug_store(struct device *cdev,
-    struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       int val = 0;
-
-       if (sscanf(buf, "%d", &val) != 1)
-               return -EINVAL;
-
-       ioc->fwfault_debug = val;
-       printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name,
-           ioc->fwfault_debug);
-       return strlen(buf);
-}
-static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
-    _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
-
-
-/**
- * _ctl_ioc_reset_count_show - ioc reset count
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is firmware queue depth limit
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
-    char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count);
-}
-static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
-    _ctl_ioc_reset_count_show, NULL);
-
-/**
- * _ctl_ioc_reply_queue_count_show - number of reply queues
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is number of reply queues
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_ioc_reply_queue_count_show(struct device *cdev,
-        struct device_attribute *attr, char *buf)
-{
-       u8 reply_queue_count;
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       if ((ioc->facts.IOCCapabilities &
-           MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable)
-               reply_queue_count = ioc->reply_queue_count;
-       else
-               reply_queue_count = 1;
-       return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count);
-}
-static DEVICE_ATTR(reply_queue_count, S_IRUGO,
-        _ctl_ioc_reply_queue_count_show, NULL);
-
-/**
- * _ctl_BRM_status_show - Backup Rail Monitor Status
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is number of reply queues
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr,
-       char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 backup_rail_monitor_status = 0;
-       u16 ioc_status;
-       int sz;
-       ssize_t rc = 0;
-
-       if (!ioc->is_warpdrive) {
-               printk(MPT2SAS_ERR_FMT "%s: BRM attribute is only for"\
-                   "warpdrive\n", ioc->name, __func__);
-               goto out;
-       }
-       /* pci_access_mutex lock acquired by sysfs show path */
-       mutex_lock(&ioc->pci_access_mutex);
-       if (ioc->pci_error_recovery || ioc->remove_host) {
-               mutex_unlock(&ioc->pci_access_mutex);
-               return 0;
-       }
-
-       /* allocate upto GPIOVal 36 entries */
-       sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
-       io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
-       if (!io_unit_pg3) {
-               printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"\
-                   "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz);
-               goto out;
-       }
-
-       if (mpt2sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
-           0) {
-               printk(MPT2SAS_ERR_FMT
-                   "%s: failed reading iounit_pg3\n", ioc->name,
-                   __func__);
-               goto out;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "%s: iounit_pg3 failed with"\
-                   "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status);
-               goto out;
-       }
-
-       if (io_unit_pg3->GPIOCount < 25) {
-               printk(MPT2SAS_ERR_FMT "%s: iounit_pg3->GPIOCount less than"\
-                    "25 entries, detected (%d) entries\n", ioc->name, __func__,
-                   io_unit_pg3->GPIOCount);
-               goto out;
-       }
-
-       /* BRM status is in bit zero of GPIOVal[24] */
-       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
-       rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
-
- out:
-       kfree(io_unit_pg3);
-       mutex_unlock(&ioc->pci_access_mutex);
-       return rc;
-}
-static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL);
-
-struct DIAG_BUFFER_START {
-       __le32 Size;
-       __le32 DiagVersion;
-       u8 BufferType;
-       u8 Reserved[3];
-       __le32 Reserved1;
-       __le32 Reserved2;
-       __le32 Reserved3;
-};
-/**
- * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_host_trace_buffer_size_show(struct device *cdev,
-    struct device_attribute *attr, char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       u32 size = 0;
-       struct DIAG_BUFFER_START *request_data;
-
-       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
-               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
-                   "registered\n", ioc->name, __func__);
-               return 0;
-       }
-
-       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
-                   "registered\n", ioc->name, __func__);
-               return 0;
-       }
-
-       request_data = (struct DIAG_BUFFER_START *)
-           ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
-       if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
-           le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
-           le32_to_cpu(request_data->Reserved3) == 0x4742444c)
-               size = le32_to_cpu(request_data->Size);
-
-       ioc->ring_buffer_sz = size;
-       return snprintf(buf, PAGE_SIZE, "%d\n", size);
-}
-static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
-        _ctl_host_trace_buffer_size_show, NULL);
-
-/**
- * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- *
- * You will only be able to read 4k bytes of ring buffer at a time.
- * In order to read beyond 4k bytes, you will have to write out the
- * offset to the same attribute, it will move the pointer.
- */
-static ssize_t
-_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
-     char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       void *request_data;
-       u32 size;
-
-       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
-               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
-                   "registered\n", ioc->name, __func__);
-               return 0;
-       }
-
-       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
-               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
-                   "registered\n", ioc->name, __func__);
-               return 0;
-       }
-
-       if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
-               return 0;
-
-       size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
-       size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
-       request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
-       memcpy(buf, request_data, size);
-       return size;
-}
-
-static ssize_t
-_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
-    const char *buf, size_t count)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       int val = 0;
-
-       if (sscanf(buf, "%d", &val) != 1)
-               return -EINVAL;
-
-       ioc->ring_buffer_offset = val;
-       return strlen(buf);
-}
-static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
-    _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
-
-/*****************************************/
-
-/**
- * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * A sysfs 'read/write' shost attribute.
- *
- * This is a mechnism to post/release host_trace_buffers
- */
-static ssize_t
-_ctl_host_trace_buffer_enable_show(struct device *cdev,
-    struct device_attribute *attr, char *buf)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
-          ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0))
-               return snprintf(buf, PAGE_SIZE, "off\n");
-       else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-           MPT2_DIAG_BUFFER_IS_RELEASED))
-               return snprintf(buf, PAGE_SIZE, "release\n");
-       else
-               return snprintf(buf, PAGE_SIZE, "post\n");
-}
-
-static ssize_t
-_ctl_host_trace_buffer_enable_store(struct device *cdev,
-    struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct Scsi_Host *shost = class_to_shost(cdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       char str[10] = "";
-       struct mpt2_diag_register diag_register;
-       u8 issue_reset = 0;
-
-       if (sscanf(buf, "%9s", str) != 1)
-               return -EINVAL;
-
-       if (!strcmp(str, "post")) {
-               /* exit out if host buffers are already posted */
-               if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
-                   (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-                   MPT2_DIAG_BUFFER_IS_REGISTERED) &&
-                   ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-                   MPT2_DIAG_BUFFER_IS_RELEASED) == 0))
-                       goto out;
-               memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
-               printk(MPT2SAS_INFO_FMT "posting host trace buffers\n",
-                   ioc->name);
-               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
-               diag_register.requested_buffer_size = (1024 * 1024);
-               diag_register.unique_id = 0x7075900;
-               ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
-               _ctl_diag_register_2(ioc,  &diag_register);
-       } else if (!strcmp(str, "release")) {
-               /* exit out if host buffers are already released */
-               if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
-                       goto out;
-               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-                   MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)
-                       goto out;
-               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
-                   MPT2_DIAG_BUFFER_IS_RELEASED))
-                       goto out;
-               printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n",
-                   ioc->name);
-               _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset);
-       }
-
- out:
-       return strlen(buf);
-}
-static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
-    _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store);
-
-struct device_attribute *mpt2sas_host_attrs[] = {
-       &dev_attr_version_fw,
-       &dev_attr_version_bios,
-       &dev_attr_version_mpi,
-       &dev_attr_version_product,
-       &dev_attr_version_nvdata_persistent,
-       &dev_attr_version_nvdata_default,
-       &dev_attr_board_name,
-       &dev_attr_board_assembly,
-       &dev_attr_board_tracer,
-       &dev_attr_io_delay,
-       &dev_attr_device_delay,
-       &dev_attr_logging_level,
-       &dev_attr_fwfault_debug,
-       &dev_attr_fw_queue_depth,
-       &dev_attr_host_sas_address,
-       &dev_attr_ioc_reset_count,
-       &dev_attr_host_trace_buffer_size,
-       &dev_attr_host_trace_buffer,
-       &dev_attr_host_trace_buffer_enable,
-       &dev_attr_reply_queue_count,
-       &dev_attr_BRM_status,
-       NULL,
-};
-
-/**
- * _ctl_device_sas_address_show - sas address
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the sas address for the target
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
-    char *buf)
-{
-       struct scsi_device *sdev = to_scsi_device(dev);
-       struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
-
-       return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
-           (unsigned long long)sas_device_priv_data->sas_target->sas_address);
-}
-static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
-
-/**
- * _ctl_device_handle_show - device handle
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
- *
- * This is the firmware assigned device handle
- *
- * A sysfs 'read-only' shost attribute.
- */
-static ssize_t
-_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
-    char *buf)
-{
-       struct scsi_device *sdev = to_scsi_device(dev);
-       struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
-
-       return snprintf(buf, PAGE_SIZE, "0x%04x\n",
-           sas_device_priv_data->sas_target->handle);
-}
-static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
-
-struct device_attribute *mpt2sas_dev_attrs[] = {
-       &dev_attr_sas_address,
-       &dev_attr_sas_device_handle,
-       NULL,
-};
-
-static const struct file_operations ctl_fops = {
-       .owner = THIS_MODULE,
-       .unlocked_ioctl = _ctl_ioctl,
-       .poll = _ctl_poll,
-       .fasync = _ctl_fasync,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = _ctl_ioctl_compat,
-#endif
-       .llseek = noop_llseek,
-};
-
-static struct miscdevice ctl_dev = {
-       .minor  = MPT2SAS_MINOR,
-       .name   = MPT2SAS_DEV_NAME,
-       .fops   = &ctl_fops,
-};
-
-/**
- * mpt2sas_ctl_init - main entry point for ctl.
- *
- */
-void
-mpt2sas_ctl_init(void)
-{
-       async_queue = NULL;
-       if (misc_register(&ctl_dev) < 0)
-               printk(KERN_ERR "%s can't register misc device [minor=%d]\n",
-                   MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
-
-       init_waitqueue_head(&ctl_poll_wait);
-}
-
-/**
- * mpt2sas_ctl_exit - exit point for ctl
- *
- */
-void
-mpt2sas_ctl_exit(void)
-{
-       struct MPT2SAS_ADAPTER *ioc;
-       int i;
-
-       list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
-
-               /* free memory associated to diag buffers */
-               for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
-                       if (!ioc->diag_buffer[i])
-                               continue;
-                       pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
-                           ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
-                       ioc->diag_buffer[i] = NULL;
-                       ioc->diag_buffer_status[i] = 0;
-               }
-
-               kfree(ioc->event_log);
-       }
-       misc_deregister(&ctl_dev);
-}
-
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
deleted file mode 100644 (file)
index 46b2fc5..0000000
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Management Module Support for MPT (Message Passing Technology) based
- * controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_CTL_H_INCLUDED
-#define MPT2SAS_CTL_H_INCLUDED
-
-#ifdef __KERNEL__
-#include <linux/miscdevice.h>
-#endif
-
-#define MPT2SAS_DEV_NAME       "mpt2ctl"
-#define MPT2_MAGIC_NUMBER      'L'
-#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
-
-/**
- * IOCTL opcodes
- */
-#define MPT2IOCINFO    _IOWR(MPT2_MAGIC_NUMBER, 17, \
-    struct mpt2_ioctl_iocinfo)
-#define MPT2COMMAND    _IOWR(MPT2_MAGIC_NUMBER, 20, \
-    struct mpt2_ioctl_command)
-#ifdef CONFIG_COMPAT
-#define MPT2COMMAND32  _IOWR(MPT2_MAGIC_NUMBER, 20, \
-    struct mpt2_ioctl_command32)
-#endif
-#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \
-    struct mpt2_ioctl_eventquery)
-#define MPT2EVENTENABLE        _IOWR(MPT2_MAGIC_NUMBER, 22, \
-    struct mpt2_ioctl_eventenable)
-#define MPT2EVENTREPORT        _IOWR(MPT2_MAGIC_NUMBER, 23, \
-    struct mpt2_ioctl_eventreport)
-#define MPT2HARDRESET  _IOWR(MPT2_MAGIC_NUMBER, 24, \
-    struct mpt2_ioctl_diag_reset)
-#define MPT2BTDHMAPPING        _IOWR(MPT2_MAGIC_NUMBER, 31, \
-    struct mpt2_ioctl_btdh_mapping)
-
-/* diag buffer support */
-#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \
-    struct mpt2_diag_register)
-#define MPT2DIAGRELEASE        _IOWR(MPT2_MAGIC_NUMBER, 27, \
-    struct mpt2_diag_release)
-#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \
-    struct mpt2_diag_unregister)
-#define MPT2DIAGQUERY  _IOWR(MPT2_MAGIC_NUMBER, 29, \
-    struct mpt2_diag_query)
-#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \
-    struct mpt2_diag_read_buffer)
-
-/**
- * struct mpt2_ioctl_header - main header structure
- * @ioc_number -  IOC unit number
- * @port_number - IOC port number
- * @max_data_size - maximum number bytes to transfer on read
- */
-struct mpt2_ioctl_header {
-       uint32_t ioc_number;
-       uint32_t port_number;
-       uint32_t max_data_size;
-};
-
-/**
- * struct mpt2_ioctl_diag_reset - diagnostic reset
- * @hdr - generic header
- */
-struct mpt2_ioctl_diag_reset {
-       struct mpt2_ioctl_header hdr;
-};
-
-
-/**
- * struct mpt2_ioctl_pci_info - pci device info
- * @device - pci device id
- * @function - pci function id
- * @bus - pci bus id
- * @segment_id - pci segment id
- */
-struct mpt2_ioctl_pci_info {
-       union {
-               struct {
-                       uint32_t device:5;
-                       uint32_t function:3;
-                       uint32_t bus:24;
-               } bits;
-               uint32_t  word;
-       } u;
-       uint32_t segment_id;
-};
-
-
-#define MPT2_IOCTL_INTERFACE_SCSI      (0x00)
-#define MPT2_IOCTL_INTERFACE_FC                (0x01)
-#define MPT2_IOCTL_INTERFACE_FC_IP     (0x02)
-#define MPT2_IOCTL_INTERFACE_SAS       (0x03)
-#define MPT2_IOCTL_INTERFACE_SAS2      (0x04)
-#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200      (0x05)
-#define MPT2_IOCTL_VERSION_LENGTH      (32)
-
-/**
- * struct mpt2_ioctl_iocinfo - generic controller info
- * @hdr - generic header
- * @adapter_type - type of adapter (spi, fc, sas)
- * @port_number - port number
- * @pci_id - PCI Id
- * @hw_rev - hardware revision
- * @sub_system_device - PCI subsystem Device ID
- * @sub_system_vendor - PCI subsystem Vendor ID
- * @rsvd0 - reserved
- * @firmware_version - firmware version
- * @bios_version - BIOS version
- * @driver_version - driver version - 32 ASCII characters
- * @rsvd1 - reserved
- * @scsi_id - scsi id of adapter 0
- * @rsvd2 - reserved
- * @pci_information - pci info (2nd revision)
- */
-struct mpt2_ioctl_iocinfo {
-       struct mpt2_ioctl_header hdr;
-       uint32_t adapter_type;
-       uint32_t port_number;
-       uint32_t pci_id;
-       uint32_t hw_rev;
-       uint32_t subsystem_device;
-       uint32_t subsystem_vendor;
-       uint32_t rsvd0;
-       uint32_t firmware_version;
-       uint32_t bios_version;
-       uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
-       uint8_t rsvd1;
-       uint8_t scsi_id;
-       uint16_t rsvd2;
-       struct mpt2_ioctl_pci_info pci_information;
-};
-
-
-/* number of event log entries */
-#define MPT2SAS_CTL_EVENT_LOG_SIZE (50)
-
-/**
- * struct mpt2_ioctl_eventquery - query event count and type
- * @hdr - generic header
- * @event_entries - number of events returned by get_event_report
- * @rsvd - reserved
- * @event_types - type of events currently being captured
- */
-struct mpt2_ioctl_eventquery {
-       struct mpt2_ioctl_header hdr;
-       uint16_t event_entries;
-       uint16_t rsvd;
-       uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
-};
-
-/**
- * struct mpt2_ioctl_eventenable - enable/disable event capturing
- * @hdr - generic header
- * @event_types - toggle off/on type of events to be captured
- */
-struct mpt2_ioctl_eventenable {
-       struct mpt2_ioctl_header hdr;
-       uint32_t event_types[4];
-};
-
-#define MPT2_EVENT_DATA_SIZE (192)
-/**
- * struct MPT2_IOCTL_EVENTS -
- * @event - the event that was reported
- * @context - unique value for each event assigned by driver
- * @data - event data returned in fw reply message
- */
-struct MPT2_IOCTL_EVENTS {
-       uint32_t event;
-       uint32_t context;
-       uint8_t data[MPT2_EVENT_DATA_SIZE];
-};
-
-/**
- * struct mpt2_ioctl_eventreport - returing event log
- * @hdr - generic header
- * @event_data - (see struct MPT2_IOCTL_EVENTS)
- */
-struct mpt2_ioctl_eventreport {
-       struct mpt2_ioctl_header hdr;
-       struct MPT2_IOCTL_EVENTS event_data[1];
-};
-
-/**
- * struct mpt2_ioctl_command - generic mpt firmware passthru ioctl
- * @hdr - generic header
- * @timeout - command timeout in seconds. (if zero then use driver default
- *  value).
- * @reply_frame_buf_ptr - reply location
- * @data_in_buf_ptr - destination for read
- * @data_out_buf_ptr - data source for write
- * @sense_data_ptr - sense data location
- * @max_reply_bytes - maximum number of reply bytes to be sent to app.
- * @data_in_size - number bytes for data transfer in (read)
- * @data_out_size - number bytes for data transfer out (write)
- * @max_sense_bytes - maximum number of bytes for auto sense buffers
- * @data_sge_offset - offset in words from the start of the request message to
- * the first SGL
- * @mf[1];
- */
-struct mpt2_ioctl_command {
-       struct mpt2_ioctl_header hdr;
-       uint32_t timeout;
-       void __user *reply_frame_buf_ptr;
-       void __user *data_in_buf_ptr;
-       void __user *data_out_buf_ptr;
-       void __user *sense_data_ptr;
-       uint32_t max_reply_bytes;
-       uint32_t data_in_size;
-       uint32_t data_out_size;
-       uint32_t max_sense_bytes;
-       uint32_t data_sge_offset;
-       uint8_t mf[1];
-};
-
-#ifdef CONFIG_COMPAT
-struct mpt2_ioctl_command32 {
-       struct mpt2_ioctl_header hdr;
-       uint32_t timeout;
-       uint32_t reply_frame_buf_ptr;
-       uint32_t data_in_buf_ptr;
-       uint32_t data_out_buf_ptr;
-       uint32_t sense_data_ptr;
-       uint32_t max_reply_bytes;
-       uint32_t data_in_size;
-       uint32_t data_out_size;
-       uint32_t max_sense_bytes;
-       uint32_t data_sge_offset;
-       uint8_t mf[1];
-};
-#endif
-
-/**
- * struct mpt2_ioctl_btdh_mapping - mapping info
- * @hdr - generic header
- * @id - target device identification number
- * @bus - SCSI bus number that the target device exists on
- * @handle - device handle for the target device
- * @rsvd - reserved
- *
- * To obtain a bus/id the application sets
- * handle to valid handle, and bus/id to 0xFFFF.
- *
- * To obtain the device handle the application sets
- * bus/id valid value, and the handle to 0xFFFF.
- */
-struct mpt2_ioctl_btdh_mapping {
-       struct mpt2_ioctl_header hdr;
-       uint32_t id;
-       uint32_t bus;
-       uint16_t handle;
-       uint16_t rsvd;
-};
-
-
-/* status bits for ioc->diag_buffer_status */
-#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
-#define MPT2_DIAG_BUFFER_IS_RELEASED   (0x02)
-#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
-
-/* application flags for mpt2_diag_register, mpt2_diag_query */
-#define MPT2_APP_FLAGS_APP_OWNED       (0x0001)
-#define MPT2_APP_FLAGS_BUFFER_VALID    (0x0002)
-#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS        (0x0004)
-
-/* flags for mpt2_diag_read_buffer */
-#define MPT2_FLAGS_REREGISTER          (0x0001)
-
-#define MPT2_PRODUCT_SPECIFIC_DWORDS           23
-
-/**
- * struct mpt2_diag_register - application register with driver
- * @hdr - generic header
- * @reserved -
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @application_flags - misc flags
- * @diagnostic_flags - specifies flags affecting command processing
- * @product_specific - product specific information
- * @requested_buffer_size - buffers size in bytes
- * @unique_id - tag specified by application that is used to signal ownership
- *  of the buffer.
- *
- * This will allow the driver to setup any required buffers that will be
- * needed by firmware to communicate with the driver.
- */
-struct mpt2_diag_register {
-       struct mpt2_ioctl_header hdr;
-       uint8_t reserved;
-       uint8_t buffer_type;
-       uint16_t application_flags;
-       uint32_t diagnostic_flags;
-       uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
-       uint32_t requested_buffer_size;
-       uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_unregister - application unregister with driver
- * @hdr - generic header
- * @unique_id - tag uniquely identifies the buffer to be unregistered
- *
- * This will allow the driver to cleanup any memory allocated for diag
- * messages and to free up any resources.
- */
-struct mpt2_diag_unregister {
-       struct mpt2_ioctl_header hdr;
-       uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_query - query relevant info associated with diag buffers
- * @hdr - generic header
- * @reserved -
- * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
- * @application_flags - misc flags
- * @diagnostic_flags - specifies flags affecting command processing
- * @product_specific - product specific information
- * @total_buffer_size - diag buffer size in bytes
- * @driver_added_buffer_size - size of extra space appended to end of buffer
- * @unique_id - unique id associated with this buffer.
- *
- * The application will send only buffer_type and unique_id.  Driver will
- * inspect unique_id first, if valid, fill in all the info.  If unique_id is
- * 0x00, the driver will return info specified by Buffer Type.
- */
-struct mpt2_diag_query {
-       struct mpt2_ioctl_header hdr;
-       uint8_t reserved;
-       uint8_t buffer_type;
-       uint16_t application_flags;
-       uint32_t diagnostic_flags;
-       uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
-       uint32_t total_buffer_size;
-       uint32_t driver_added_buffer_size;
-       uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_release -  request to send Diag Release Message to firmware
- * @hdr - generic header
- * @unique_id - tag uniquely identifies the buffer to be released
- *
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
- */
-struct mpt2_diag_release {
-       struct mpt2_ioctl_header hdr;
-       uint32_t unique_id;
-};
-
-/**
- * struct mpt2_diag_read_buffer - request for copy of the diag buffer
- * @hdr - generic header
- * @status -
- * @reserved -
- * @flags - misc flags
- * @starting_offset - starting offset within drivers buffer where to start
- *  reading data at into the specified application buffer
- * @bytes_to_read - number of bytes to copy from the drivers buffer into the
- *  application buffer starting at starting_offset.
- * @unique_id - unique id associated with this buffer.
- * @diagnostic_data - data payload
- */
-struct mpt2_diag_read_buffer {
-       struct mpt2_ioctl_header hdr;
-       uint8_t status;
-       uint8_t reserved;
-       uint16_t flags;
-       uint32_t starting_offset;
-       uint32_t bytes_to_read;
-       uint32_t unique_id;
-       uint32_t diagnostic_data[1];
-};
-
-#endif /* MPT2SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
deleted file mode 100644 (file)
index 277120d..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Logging Support for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
- * USA.
- */
-
-#ifndef MPT2SAS_DEBUG_H_INCLUDED
-#define MPT2SAS_DEBUG_H_INCLUDED
-
-#define MPT_DEBUG                      0x00000001
-#define MPT_DEBUG_MSG_FRAME            0x00000002
-#define MPT_DEBUG_SG                   0x00000004
-#define MPT_DEBUG_EVENTS               0x00000008
-#define MPT_DEBUG_EVENT_WORK_TASK      0x00000010
-#define MPT_DEBUG_INIT                 0x00000020
-#define MPT_DEBUG_EXIT                 0x00000040
-#define MPT_DEBUG_FAIL                 0x00000080
-#define MPT_DEBUG_TM                   0x00000100
-#define MPT_DEBUG_REPLY                        0x00000200
-#define MPT_DEBUG_HANDSHAKE            0x00000400
-#define MPT_DEBUG_CONFIG               0x00000800
-#define MPT_DEBUG_DL                   0x00001000
-#define MPT_DEBUG_RESET                        0x00002000
-#define MPT_DEBUG_SCSI                 0x00004000
-#define MPT_DEBUG_IOCTL                        0x00008000
-#define MPT_DEBUG_CSMISAS              0x00010000
-#define MPT_DEBUG_SAS                  0x00020000
-#define MPT_DEBUG_TRANSPORT            0x00040000
-#define MPT_DEBUG_TASK_SET_FULL                0x00080000
-
-#define MPT_DEBUG_TARGET_MODE          0x00100000
-
-
-/*
- * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig
- */
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS)                      \
-{                                                              \
-       if (IOC->logging_level & BITS)                          \
-               CMD;                                            \
-}
-#else
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
-#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
-
-
-/*
- * debug macros
- */
-
-#define dprintk(IOC, CMD)                      \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
-
-#define dsgprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
-
-#define devtprintk(IOC, CMD)                   \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
-
-#define dewtprintk(IOC, CMD)           \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
-
-#define dinitprintk(IOC, CMD)                  \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
-
-#define dexitprintk(IOC, CMD)                  \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
-
-#define dfailprintk(IOC, CMD)                  \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
-
-#define dtmprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
-
-#define dreplyprintk(IOC, CMD)                 \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
-
-#define dhsprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
-
-#define dcprintk(IOC, CMD)                     \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
-
-#define ddlprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
-
-#define drsprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
-
-#define dsprintk(IOC, CMD)                     \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
-
-#define dctlprintk(IOC, CMD)                   \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
-
-#define dcsmisasprintk(IOC, CMD)               \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
-
-#define dsasprintk(IOC, CMD)                   \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
-
-#define dsastransport(IOC, CMD)                \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
-
-#define dmfprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
-
-#define dtsfprintk(IOC, CMD)                   \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
-
-#define dtransportprintk(IOC, CMD)                     \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
-
-#define dTMprintk(IOC, CMD)                    \
-       MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE)
-
-/* inline functions for dumping debug data*/
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _debug_dump_mf - print message frame contents
- * @mpi_request: pointer to message frame
- * @sz: number of dwords
- */
-static inline void
-_debug_dump_mf(void *mpi_request, int sz)
-{
-       int i;
-       __le32 *mfp = (__le32 *)mpi_request;
-
-       printk(KERN_INFO "mf:\n\t");
-       for (i = 0; i < sz; i++) {
-               if (i && ((i % 8) == 0))
-                       printk("\n\t");
-               printk("%08x ", le32_to_cpu(mfp[i]));
-       }
-       printk("\n");
-}
-#else
-#define _debug_dump_mf(mpi_request, sz)
-#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
-
-#endif /* MPT2SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
deleted file mode 100644 (file)
index 0ad09b2..0000000
+++ /dev/null
@@ -1,8855 +0,0 @@
-/*
- * Scsi Host Layer for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/blkdev.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/aer.h>
-#include <linux/raid_class.h>
-#include <linux/slab.h>
-
-#include <asm/unaligned.h>
-
-#include "mpt2sas_base.h"
-
-MODULE_AUTHOR(MPT2SAS_AUTHOR);
-MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MPT2SAS_DRIVER_VERSION);
-
-#define RAID_CHANNEL 1
-
-/* forward proto's */
-static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_node *sas_expander);
-static void _firmware_event_work(struct work_struct *work);
-
-static u8 _scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid);
-
-static void _scsih_scan_start(struct Scsi_Host *shost);
-static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
-
-/* global parameters */
-LIST_HEAD(mpt2sas_ioc_list);
-/* global ioc lock for list operations */
-DEFINE_SPINLOCK(gioc_lock);
-/* local parameters */
-static u8 scsi_io_cb_idx = -1;
-static u8 tm_cb_idx = -1;
-static u8 ctl_cb_idx = -1;
-static u8 base_cb_idx = -1;
-static u8 port_enable_cb_idx = -1;
-static u8 transport_cb_idx = -1;
-static u8 scsih_cb_idx = -1;
-static u8 config_cb_idx = -1;
-static int mpt_ids;
-
-static u8 tm_tr_cb_idx = -1 ;
-static u8 tm_tr_volume_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 "
-    "(default=0)");
-
-static ushort max_sectors = 0xFFFF;
-module_param(max_sectors, ushort, 0);
-MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767  default=32767");
-
-static int missing_delay[2] = {-1, -1};
-module_param_array(missing_delay, int, NULL, 0);
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
-
-/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
-#define MPT2SAS_MAX_LUN (16895)
-static int max_lun = MPT2SAS_MAX_LUN;
-module_param(max_lun, int, 0);
-MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
-
-/* diag_buffer_enable is bitwise
- * bit 0 set = TRACE
- * bit 1 set = SNAPSHOT
- * bit 2 set = EXTENDED
- *
- * Either bit can be set, or both
- */
-static int diag_buffer_enable = -1;
-module_param(diag_buffer_enable, int, 0);
-MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
-       "(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
-
-static int disable_discovery = -1;
-module_param(disable_discovery, int, 0);
-MODULE_PARM_DESC(disable_discovery, " disable discovery ");
-
-/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
-static int prot_mask = 0;
-module_param(prot_mask, int, 0);
-MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
-
-/**
- * struct sense_info - common structure for obtaining sense keys
- * @skey: sense key
- * @asc: additional sense code
- * @ascq: additional sense code qualifier
- */
-struct sense_info {
-       u8 skey;
-       u8 asc;
-       u8 ascq;
-};
-
-
-#define MPT2SAS_TURN_ON_PFA_LED (0xFFFC)
-#define MPT2SAS_PORT_ENABLE_COMPLETE (0xFFFD)
-#define MPT2SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
-/**
- * struct fw_event_work - firmware event struct
- * @list: link list framework
- * @work: work object (ioc->fault_reset_work_q)
- * @cancel_pending_work: flag set during reset handling
- * @ioc: per adapter object
- * @device_handle: device handle
- * @VF_ID: virtual function id
- * @VP_ID: virtual port id
- * @ignore: flag meaning this event has been marked to ignore
- * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
- * @event_data: reply event data payload follows
- *
- * This object stored on ioc->fw_event_list.
- */
-struct fw_event_work {
-       struct list_head        list;
-       u8                      cancel_pending_work;
-       struct delayed_work     delayed_work;
-       struct MPT2SAS_ADAPTER *ioc;
-       u16                     device_handle;
-       u8                      VF_ID;
-       u8                      VP_ID;
-       u8                      ignore;
-       u16                     event;
-       struct kref             refcount;
-       char                    event_data[0] __aligned(4);
-};
-
-static void fw_event_work_free(struct kref *r)
-{
-       kfree(container_of(r, struct fw_event_work, refcount));
-}
-
-static void fw_event_work_get(struct fw_event_work *fw_work)
-{
-       kref_get(&fw_work->refcount);
-}
-
-static void fw_event_work_put(struct fw_event_work *fw_work)
-{
-       kref_put(&fw_work->refcount, fw_event_work_free);
-}
-
-static struct fw_event_work *alloc_fw_event_work(int len)
-{
-       struct fw_event_work *fw_event;
-
-       fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
-       if (!fw_event)
-               return NULL;
-
-       kref_init(&fw_event->refcount);
-       return fw_event;
-}
-
-/* raid transport support */
-static struct raid_template *mpt2sas_raid_template;
-
-/**
- * struct _scsi_io_transfer - scsi io transfer
- * @handle: sas device handle (assigned by firmware)
- * @is_raid: flag set for hidden raid components
- * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
- * @data_length: data transfer length
- * @data_dma: dma pointer to data
- * @sense: sense data
- * @lun: lun number
- * @cdb_length: cdb length
- * @cdb: cdb contents
- * @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
- * @scsi_status: scsi staus
- * @log_info: log information
- * @transfer_length: data length transfer when there is a reply message
- *
- * Used for sending internal scsi commands to devices within this module.
- * Refer to _scsi_send_scsi_io().
- */
-struct _scsi_io_transfer {
-       u16     handle;
-       u8      is_raid;
-       enum dma_data_direction dir;
-       u32     data_length;
-       dma_addr_t data_dma;
-       u8      sense[SCSI_SENSE_BUFFERSIZE];
-       u32     lun;
-       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;
-       u16     ioc_status;
-       u8      scsi_state;
-       u8      scsi_status;
-       u32     log_info;
-       u32     transfer_length;
-};
-
-/*
- * The pci device ids are defined in mpi/mpi2_cnfg.h.
- */
-static struct pci_device_id scsih_pci_table[] = {
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Falcon ~ 2008*/
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Liberator ~ 2108 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Meteor ~ 2116 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Thunderbolt ~ 2208 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Mustang ~ 2308 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* SSS6200 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
-               PCI_ANY_ID, PCI_ANY_ID },
-       {0}     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, scsih_pci_table);
-
-/**
- * _scsih_set_debug_level - global setting of ioc->logging_level.
- *
- * Note: The logging levels are defined in mpt2sas_debug.h.
- */
-static int
-_scsih_set_debug_level(const char *val, struct kernel_param *kp)
-{
-       int ret = param_set_int(val, kp);
-       struct MPT2SAS_ADAPTER *ioc;
-
-       if (ret)
-               return ret;
-
-       printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level);
-       spin_lock(&gioc_lock);
-       list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
-               ioc->logging_level = logging_level;
-       spin_unlock(&gioc_lock);
-       return 0;
-}
-module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
-    &logging_level, 0644);
-
-/**
- * _scsih_srch_boot_sas_address - search based on sas_address
- * @sas_address: sas address
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_sas_address(u64 sas_address,
-    Mpi2BootDeviceSasWwid_t *boot_device)
-{
-       return (sas_address == le64_to_cpu(boot_device->SASAddress)) ?  1 : 0;
-}
-
-/**
- * _scsih_srch_boot_device_name - search based on device name
- * @device_name: device name specified in INDENTIFY fram
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_device_name(u64 device_name,
-    Mpi2BootDeviceDeviceName_t *boot_device)
-{
-       return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
-}
-
-/**
- * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
- * @enclosure_logical_id: enclosure logical id
- * @slot_number: slot number
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static inline int
-_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
-    Mpi2BootDeviceEnclosureSlot_t *boot_device)
-{
-       return (enclosure_logical_id == le64_to_cpu(boot_device->
-           EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
-           SlotNumber)) ? 1 : 0;
-}
-
-/**
- * _scsih_is_boot_device - search for matching boot device.
- * @sas_address: sas address
- * @device_name: device name specified in INDENTIFY fram
- * @enclosure_logical_id: enclosure logical id
- * @slot_number: slot number
- * @form: specifies boot device form
- * @boot_device: boot device object from bios page 2
- *
- * Returns 1 when there's a match, 0 means no match.
- */
-static int
-_scsih_is_boot_device(u64 sas_address, u64 device_name,
-    u64 enclosure_logical_id, u16 slot, u8 form,
-    Mpi2BiosPage2BootDevice_t *boot_device)
-{
-       int rc = 0;
-
-       switch (form) {
-       case MPI2_BIOSPAGE2_FORM_SAS_WWID:
-               if (!sas_address)
-                       break;
-               rc = _scsih_srch_boot_sas_address(
-                   sas_address, &boot_device->SasWwid);
-               break;
-       case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
-               if (!enclosure_logical_id)
-                       break;
-               rc = _scsih_srch_boot_encl_slot(
-                   enclosure_logical_id,
-                   slot, &boot_device->EnclosureSlot);
-               break;
-       case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
-               if (!device_name)
-                       break;
-               rc = _scsih_srch_boot_device_name(
-                   device_name, &boot_device->DeviceName);
-               break;
-       case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
-               break;
-       }
-
-       return rc;
-}
-
-/**
- * _scsih_get_sas_address - set the sas_address for given device handle
- * @handle: device handle
- * @sas_address: sas address
- *
- * Returns 0 success, non-zero when failure
- */
-static int
-_scsih_get_sas_address(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-    u64 *sas_address)
-{
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u32 ioc_status;
-       *sas_address = 0;
-
-       if (handle <= ioc->sas_hba.num_phys) {
-               *sas_address = ioc->sas_hba.sas_address;
-               return 0;
-       }
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
-               __FILE__, __LINE__, __func__);
-               return -ENXIO;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
-               *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-               return 0;
-       }
-
-       /* we hit this becuase the given parent handle doesn't exist */
-       if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-               return -ENXIO;
-       /* else error case */
-       printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x), "
-           "failure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
-            __FILE__, __LINE__, __func__);
-       return -EIO;
-}
-
-/**
- * _scsih_determine_boot_device - determine boot device.
- * @ioc: per adapter object
- * @device: either sas_device or raid_device object
- * @is_raid: [flag] 1 = raid object, 0 = sas object
- *
- * Determines whether this device should be first reported device to
- * to scsi-ml or sas transport, this purpose is for persistent boot device.
- * There are primary, alternate, and current entries in bios page 2. The order
- * priority is primary, alternate, then current.  This routine saves
- * the corresponding device object and is_raid flag in the ioc object.
- * The saved data to be used later in _scsih_probe_boot_devices().
- */
-static void
-_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
-    void *device, u8 is_raid)
-{
-       struct _sas_device *sas_device;
-       struct _raid_device *raid_device;
-       u64 sas_address;
-       u64 device_name;
-       u64 enclosure_logical_id;
-       u16 slot;
-
-        /* only process this function when driver loads */
-       if (!ioc->is_driver_loading)
-               return;
-
-        /* no Bios, return immediately */
-       if (!ioc->bios_pg3.BiosVersion)
-               return;
-
-       if (!is_raid) {
-               sas_device = device;
-               sas_address = sas_device->sas_address;
-               device_name = sas_device->device_name;
-               enclosure_logical_id = sas_device->enclosure_logical_id;
-               slot = sas_device->slot;
-       } else {
-               raid_device = device;
-               sas_address = raid_device->wwid;
-               device_name = 0;
-               enclosure_logical_id = 0;
-               slot = 0;
-       }
-
-       if (!ioc->req_boot_device.device) {
-               if (_scsih_is_boot_device(sas_address, device_name,
-                   enclosure_logical_id, slot,
-                   (ioc->bios_pg2.ReqBootDeviceForm &
-                   MPI2_BIOSPAGE2_FORM_MASK),
-                   &ioc->bios_pg2.RequestedBootDevice)) {
-                       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                          "%s: req_boot_device(0x%016llx)\n",
-                           ioc->name, __func__,
-                           (unsigned long long)sas_address));
-                       ioc->req_boot_device.device = device;
-                       ioc->req_boot_device.is_raid = is_raid;
-               }
-       }
-
-       if (!ioc->req_alt_boot_device.device) {
-               if (_scsih_is_boot_device(sas_address, device_name,
-                   enclosure_logical_id, slot,
-                   (ioc->bios_pg2.ReqAltBootDeviceForm &
-                   MPI2_BIOSPAGE2_FORM_MASK),
-                   &ioc->bios_pg2.RequestedAltBootDevice)) {
-                       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                          "%s: req_alt_boot_device(0x%016llx)\n",
-                           ioc->name, __func__,
-                           (unsigned long long)sas_address));
-                       ioc->req_alt_boot_device.device = device;
-                       ioc->req_alt_boot_device.is_raid = is_raid;
-               }
-       }
-
-       if (!ioc->current_boot_device.device) {
-               if (_scsih_is_boot_device(sas_address, device_name,
-                   enclosure_logical_id, slot,
-                   (ioc->bios_pg2.CurrentBootDeviceForm &
-                   MPI2_BIOSPAGE2_FORM_MASK),
-                   &ioc->bios_pg2.CurrentBootDevice)) {
-                       dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
-                          "%s: current_boot_device(0x%016llx)\n",
-                           ioc->name, __func__,
-                           (unsigned long long)sas_address));
-                       ioc->current_boot_device.device = device;
-                       ioc->current_boot_device.is_raid = is_raid;
-               }
-       }
-}
-
-static struct _sas_device *
-__mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc,
-               struct MPT2SAS_TARGET *tgt_priv)
-{
-       struct _sas_device *ret;
-
-       assert_spin_locked(&ioc->sas_device_lock);
-
-       ret = tgt_priv->sdev;
-       if (ret)
-               sas_device_get(ret);
-
-       return ret;
-}
-
-static struct _sas_device *
-mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc,
-               struct MPT2SAS_TARGET *tgt_priv)
-{
-       struct _sas_device *ret;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       ret = __mpt2sas_get_sdev_from_target(ioc, tgt_priv);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       return ret;
-}
-
-
-struct _sas_device *
-__mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc,
-    u64 sas_address)
-{
-       struct _sas_device *sas_device;
-
-       assert_spin_locked(&ioc->sas_device_lock);
-
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
-               if (sas_device->sas_address == sas_address)
-                       goto found_device;
-
-       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
-               if (sas_device->sas_address == sas_address)
-                       goto found_device;
-
-       return NULL;
-
-found_device:
-       sas_device_get(sas_device);
-       return sas_device;
-}
-
-/**
- * mpt2sas_get_sdev_by_addr - sas device search
- * @ioc: per adapter object
- * @sas_address: sas address
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-struct _sas_device *
-mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc,
-    u64 sas_address)
-{
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-                       sas_address);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       return sas_device;
-}
-
-static struct _sas_device *
-__mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_device *sas_device;
-
-       assert_spin_locked(&ioc->sas_device_lock);
-
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
-               if (sas_device->handle == handle)
-                       goto found_device;
-
-       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
-               if (sas_device->handle == handle)
-                       goto found_device;
-
-       return NULL;
-
-found_device:
-       sas_device_get(sas_device);
-       return sas_device;
-}
-
-/**
- * mpt2sas_get_sdev_by_handle - sas device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-static struct _sas_device *
-mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       return sas_device;
-}
-
-/**
- * _scsih_sas_device_remove - remove sas_device from list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * If sas_device is on the list, remove it and decrement its reference count.
- */
-static void
-_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_device *sas_device)
-{
-       unsigned long flags;
-
-       if (!sas_device)
-               return;
-
-       /*
-        * The lock serializes access to the list, but we still need to verify
-        * that nobody removed the entry while we were waiting on the lock.
-        */
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       if (!list_empty(&sas_device->list)) {
-               list_del_init(&sas_device->list);
-               sas_device_put(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-
-/**
- * _scsih_sas_device_add - insert sas_device to the list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * Adding new object to the ioc->sas_device_list.
- */
-static void
-_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_device *sas_device)
-{
-       unsigned long flags;
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
-           "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
-           sas_device->handle, (unsigned long long)sas_device->sas_address));
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device_get(sas_device);
-       list_add_tail(&sas_device->list, &ioc->sas_device_list);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
-            sas_device->sas_address_parent)) {
-               _scsih_sas_device_remove(ioc, sas_device);
-       } else if (!sas_device->starget) {
-               /* When asyn scanning is enabled, its not possible to remove
-                * devices while scanning is turned on due to an oops in
-                * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
-                */
-               if (!ioc->is_driver_loading) {
-                       mpt2sas_transport_port_remove(ioc,
-                       sas_device->sas_address,
-                       sas_device->sas_address_parent);
-                       _scsih_sas_device_remove(ioc, sas_device);
-               }
-       }
-}
-
-/**
- * _scsih_sas_device_init_add - insert sas_device to the list.
- * @ioc: per adapter object
- * @sas_device: the sas_device object
- * Context: This function will acquire ioc->sas_device_lock.
- *
- * Adding new object at driver load time to the ioc->sas_device_init_list.
- */
-static void
-_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_device *sas_device)
-{
-       unsigned long flags;
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
-           "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
-           sas_device->handle, (unsigned long long)sas_device->sas_address));
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device_get(sas_device);
-       list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
-       _scsih_determine_boot_device(ioc, sas_device, 0);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_raid_device_find_by_id - raid device search
- * @ioc: per adapter object
- * @id: sas device target id
- * @channel: sas device channel
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on target id, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
-{
-       struct _raid_device *raid_device, *r;
-
-       r = NULL;
-       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
-               if (raid_device->id == id && raid_device->channel == channel) {
-                       r = raid_device;
-                       goto out;
-               }
-       }
-
- out:
-       return r;
-}
-
-/**
- * _scsih_raid_device_find_by_handle - raid device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on handle, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _raid_device *raid_device, *r;
-
-       r = NULL;
-       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
-               if (raid_device->handle != handle)
-                       continue;
-               r = raid_device;
-               goto out;
-       }
-
- out:
-       return r;
-}
-
-/**
- * _scsih_raid_device_find_by_wwid - raid device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->raid_device_lock
- *
- * This searches for raid_device based on wwid, then return raid_device
- * object.
- */
-static struct _raid_device *
-_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
-{
-       struct _raid_device *raid_device, *r;
-
-       r = NULL;
-       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
-               if (raid_device->wwid != wwid)
-                       continue;
-               r = raid_device;
-               goto out;
-       }
-
- out:
-       return r;
-}
-
-/**
- * _scsih_raid_device_add - add raid_device object
- * @ioc: per adapter object
- * @raid_device: raid_device object
- *
- * This is added to the raid_device_list link list.
- */
-static void
-_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
-    struct _raid_device *raid_device)
-{
-       unsigned long flags;
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle"
-           "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
-           raid_device->handle, (unsigned long long)raid_device->wwid));
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       list_add_tail(&raid_device->list, &ioc->raid_device_list);
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_raid_device_remove - delete raid_device object
- * @ioc: per adapter object
- * @raid_device: raid_device object
- *
- */
-static void
-_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
-    struct _raid_device *raid_device)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       list_del(&raid_device->list);
-       kfree(raid_device);
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * mpt2sas_scsih_expander_find_by_handle - expander device search
- * @ioc: per adapter object
- * @handle: expander handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for expander device based on handle, then returns the
- * sas_node object.
- */
-struct _sas_node *
-mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_node *sas_expander, *r;
-
-       r = NULL;
-       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
-               if (sas_expander->handle != handle)
-                       continue;
-               r = sas_expander;
-               goto out;
-       }
- out:
-       return r;
-}
-
-/**
- * mpt2sas_scsih_expander_find_by_sas_address - expander device search
- * @ioc: per adapter object
- * @sas_address: sas address
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * This searches for expander device based on sas_address, then returns the
- * sas_node object.
- */
-struct _sas_node *
-mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
-    u64 sas_address)
-{
-       struct _sas_node *sas_expander, *r;
-
-       r = NULL;
-       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
-               if (sas_expander->sas_address != sas_address)
-                       continue;
-               r = sas_expander;
-               goto out;
-       }
- out:
-       return r;
-}
-
-/**
- * _scsih_expander_node_add - insert expander device to the list.
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Adding new object to the ioc->sas_expander_list.
- *
- * Return nothing.
- */
-static void
-_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_node *sas_expander)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-}
-
-/**
- * _scsih_is_end_device - determines if device is an end device
- * @device_info: bitfield providing information about the device.
- * Context: none
- *
- * Returns 1 if end device.
- */
-static int
-_scsih_is_end_device(u32 device_info)
-{
-       if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
-               ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
-               (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
-               (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
-               return 1;
-       else
-               return 0;
-}
-
-/**
- * _scsih_scsi_lookup_get - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static struct scsi_cmnd *
-_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return ioc->scsi_lookup[smid - 1].scmd;
-}
-
-/**
- * _scsih_scsi_lookup_get_clear - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- * Then will derefrence the stored scmd pointer.
- */
-static inline struct scsi_cmnd *
-_scsih_scsi_lookup_get_clear(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_find_by_scmd - scmd 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 search for a scmd pointer in the scsi_lookup array,
- * returning the revelent smid.  A returned value of zero means invalid.
- */
-static u16
-_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
-    *scmd)
-{
-       u16 smid;
-       unsigned long   flags;
-       int i;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       smid = 0;
-       for (i = 0; i < ioc->scsiio_depth; i++) {
-               if (ioc->scsi_lookup[i].scmd == scmd) {
-                       smid = ioc->scsi_lookup[i].smid;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return smid;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_target - search for matching channel:id
- * @ioc: per adapter object
- * @id: target id
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
-    int channel)
-{
-       u8 found;
-       unsigned long   flags;
-       int i;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       found = 0;
-       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)) {
-                       found = 1;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return found;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
- * @ioc: per adapter object
- * @id: target id
- * @lun: lun number
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id:lun in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id,
-    unsigned int lun, int channel)
-{
-       u8 found;
-       unsigned long   flags;
-       int i;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       found = 0;
-       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 &&
-                   ioc->scsi_lookup[i].scmd->device->lun == lun)) {
-                       found = 1;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return found;
-}
-
-/**
- * _scsih_get_chain_buffer_tracker - obtain chain tracker
- * @ioc: per adapter object
- * @smid: smid associated to an IO request
- *
- * Returns chain tracker(from ioc->free_chain_list)
- */
-static struct chain_tracker *
-_scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       struct chain_tracker *chain_req;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       if (list_empty(&ioc->free_chain_list)) {
-               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not "
-                       "available\n", ioc->name));
-               return NULL;
-       }
-       chain_req = list_entry(ioc->free_chain_list.next,
-           struct chain_tracker, tracker_list);
-       list_del_init(&chain_req->tracker_list);
-       list_add_tail(&chain_req->tracker_list,
-           &ioc->scsi_lookup[smid - 1].chain_list);
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-       return chain_req;
-}
-
-/**
- * _scsih_build_scatter_gather - main sg creation routine
- * @ioc: per adapter object
- * @scmd: scsi command
- * @smid: system request message index
- * Context: none.
- *
- * The main routine that builds scatter gather table from a given
- * scsi request sent via the .queuecommand main handler.
- *
- * Returns 0 success, anything else error
- */
-static int
-_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
-    struct scsi_cmnd *scmd, u16 smid)
-{
-       Mpi2SCSIIORequest_t *mpi_request;
-       dma_addr_t chain_dma;
-       struct scatterlist *sg_scmd;
-       void *sg_local, *chain;
-       u32 chain_offset;
-       u32 chain_length;
-       u32 chain_flags;
-       int sges_left;
-       u32 sges_in_segment;
-       u32 sgl_flags;
-       u32 sgl_flags_last_element;
-       u32 sgl_flags_end_buffer;
-       struct chain_tracker *chain_req;
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-
-       /* init scatter gather flags */
-       sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
-       if (scmd->sc_data_direction == DMA_TO_DEVICE)
-               sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
-       sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
-           << MPI2_SGE_FLAGS_SHIFT;
-       sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
-           << MPI2_SGE_FLAGS_SHIFT;
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-
-       sg_scmd = scsi_sglist(scmd);
-       sges_left = scsi_dma_map(scmd);
-       if (sges_left < 0) {
-               sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
-               " failed: request for %d bytes!\n", scsi_bufflen(scmd));
-               return -ENOMEM;
-       }
-
-       sg_local = &mpi_request->SGL;
-       sges_in_segment = ioc->max_sges_in_main_message;
-       if (sges_left <= sges_in_segment)
-               goto fill_in_last_segment;
-
-       mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
-           (sges_in_segment * ioc->sge_size))/4;
-
-       /* fill in main message segment when there is a chain following */
-       while (sges_in_segment) {
-               if (sges_in_segment == 1)
-                       ioc->base_add_sg_single(sg_local,
-                           sgl_flags_last_element | sg_dma_len(sg_scmd),
-                           sg_dma_address(sg_scmd));
-               else
-                       ioc->base_add_sg_single(sg_local, sgl_flags |
-                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
-               sg_scmd = sg_next(sg_scmd);
-               sg_local += ioc->sge_size;
-               sges_left--;
-               sges_in_segment--;
-       }
-
-       /* initializing the chain flags and pointers */
-       chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
-       chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
-       if (!chain_req)
-               return -1;
-       chain = chain_req->chain_buffer;
-       chain_dma = chain_req->chain_buffer_dma;
-       do {
-               sges_in_segment = (sges_left <=
-                   ioc->max_sges_in_chain_message) ? sges_left :
-                   ioc->max_sges_in_chain_message;
-               chain_offset = (sges_left == sges_in_segment) ?
-                   0 : (sges_in_segment * ioc->sge_size)/4;
-               chain_length = sges_in_segment * ioc->sge_size;
-               if (chain_offset) {
-                       chain_offset = chain_offset <<
-                           MPI2_SGE_CHAIN_OFFSET_SHIFT;
-                       chain_length += ioc->sge_size;
-               }
-               ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
-                   chain_length, chain_dma);
-               sg_local = chain;
-               if (!chain_offset)
-                       goto fill_in_last_segment;
-
-               /* fill in chain segments */
-               while (sges_in_segment) {
-                       if (sges_in_segment == 1)
-                               ioc->base_add_sg_single(sg_local,
-                                   sgl_flags_last_element |
-                                   sg_dma_len(sg_scmd),
-                                   sg_dma_address(sg_scmd));
-                       else
-                               ioc->base_add_sg_single(sg_local, sgl_flags |
-                                   sg_dma_len(sg_scmd),
-                                   sg_dma_address(sg_scmd));
-                       sg_scmd = sg_next(sg_scmd);
-                       sg_local += ioc->sge_size;
-                       sges_left--;
-                       sges_in_segment--;
-               }
-
-               chain_req = _scsih_get_chain_buffer_tracker(ioc, smid);
-               if (!chain_req)
-                       return -1;
-               chain = chain_req->chain_buffer;
-               chain_dma = chain_req->chain_buffer_dma;
-       } while (1);
-
-
- fill_in_last_segment:
-
-       /* fill the last segment */
-       while (sges_left) {
-               if (sges_left == 1)
-                       ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
-                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
-               else
-                       ioc->base_add_sg_single(sg_local, sgl_flags |
-                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
-               sg_scmd = sg_next(sg_scmd);
-               sg_local += ioc->sge_size;
-               sges_left--;
-       }
-
-       return 0;
-}
-
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
-{
-       struct Scsi_Host *shost = sdev->host;
-       int max_depth;
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       max_depth = shost->can_queue;
-
-       /* limit max device queue for SATA to 32 */
-       sas_device_priv_data = sdev->hostdata;
-       if (!sas_device_priv_data)
-               goto not_sata;
-       sas_target_priv_data = sas_device_priv_data->sas_target;
-       if (!sas_target_priv_data)
-               goto not_sata;
-       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
-               goto not_sata;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data);
-       if (sas_device) {
-               if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
-                       max_depth = MPT2SAS_SATA_QUEUE_DEPTH;
-
-               sas_device_put(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- not_sata:
-       if (!sdev->tagged_supported)
-               max_depth = 1;
-       if (qdepth > max_depth)
-               qdepth = max_depth;
-       return scsi_change_queue_depth(sdev, qdepth);
-}
-
-/**
- * _scsih_target_alloc - target add routine
- * @starget: scsi target struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_target_alloc(struct scsi_target *starget)
-{
-       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct _sas_device *sas_device;
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       struct sas_rphy *rphy;
-
-       sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
-                                      GFP_KERNEL);
-       if (!sas_target_priv_data)
-               return -ENOMEM;
-
-       starget->hostdata = sas_target_priv_data;
-       sas_target_priv_data->starget = starget;
-       sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
-
-       /* RAID volumes */
-       if (starget->channel == RAID_CHANNEL) {
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
-                   starget->channel);
-               if (raid_device) {
-                       sas_target_priv_data->handle = raid_device->handle;
-                       sas_target_priv_data->sas_address = raid_device->wwid;
-                       sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
-                       if (ioc->is_warpdrive)
-                               sas_target_priv_data->raid_device = raid_device;
-                       raid_device->starget = starget;
-               }
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-               return 0;
-       }
-
-       /* sas/sata devices */
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       rphy = dev_to_rphy(starget->dev.parent);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-          rphy->identify.sas_address);
-
-       if (sas_device) {
-               sas_target_priv_data->handle = sas_device->handle;
-               sas_target_priv_data->sas_address = sas_device->sas_address;
-               sas_target_priv_data->sdev = sas_device;
-               sas_device->starget = starget;
-               sas_device->id = starget->id;
-               sas_device->channel = starget->channel;
-               if (test_bit(sas_device->handle, ioc->pd_handles))
-                       sas_target_priv_data->flags |=
-                           MPT_TARGET_FLAGS_RAID_COMPONENT;
-
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       return 0;
-}
-
-/**
- * _scsih_target_destroy - target destroy routine
- * @starget: scsi target struct
- *
- * Returns nothing.
- */
-static void
-_scsih_target_destroy(struct scsi_target *starget)
-{
-       struct Scsi_Host *shost = dev_to_shost(&starget->dev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct _sas_device *sas_device;
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       struct sas_rphy *rphy;
-
-       sas_target_priv_data = starget->hostdata;
-       if (!sas_target_priv_data)
-               return;
-
-       if (starget->channel == RAID_CHANNEL) {
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
-                   starget->channel);
-               if (raid_device) {
-                       raid_device->starget = NULL;
-                       raid_device->sdev = NULL;
-               }
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-               goto out;
-       }
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       rphy = dev_to_rphy(starget->dev.parent);
-       sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data);
-       if (sas_device && (sas_device->starget == starget) &&
-           (sas_device->id == starget->id) &&
-           (sas_device->channel == starget->channel))
-               sas_device->starget = NULL;
-
-       if (sas_device) {
-               /*
-                * Corresponding get() is in _scsih_target_alloc()
-                */
-               sas_target_priv_data->sdev = NULL;
-               sas_device_put(sas_device);
-
-               sas_device_put(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
- out:
-       kfree(sas_target_priv_data);
-       starget->hostdata = NULL;
-}
-
-/**
- * _scsih_slave_alloc - device add routine
- * @sdev: scsi device struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_slave_alloc(struct scsi_device *sdev)
-{
-       struct Scsi_Host *shost;
-       struct MPT2SAS_ADAPTER *ioc;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_target *starget;
-       struct _raid_device *raid_device;
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
-                                      GFP_KERNEL);
-       if (!sas_device_priv_data)
-               return -ENOMEM;
-
-       sas_device_priv_data->lun = sdev->lun;
-       sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
-
-       starget = scsi_target(sdev);
-       sas_target_priv_data = starget->hostdata;
-       sas_target_priv_data->num_luns++;
-       sas_device_priv_data->sas_target = sas_target_priv_data;
-       sdev->hostdata = sas_device_priv_data;
-       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
-               sdev->no_uld_attach = 1;
-
-       shost = dev_to_shost(&starget->dev);
-       ioc = shost_priv(shost);
-       if (starget->channel == RAID_CHANNEL) {
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_id(ioc,
-                   starget->id, starget->channel);
-               if (raid_device)
-                       raid_device->sdev = sdev; /* raid is single lun */
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       }
-
-       if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-                               sas_target_priv_data->sas_address);
-               if (sas_device && (sas_device->starget == NULL)) {
-                       sdev_printk(KERN_INFO, sdev,
-                            "%s : sas_device->starget set to starget @ %d\n",
-                            __func__, __LINE__);
-                       sas_device->starget = starget;
-               }
-
-               if (sas_device)
-                       sas_device_put(sas_device);
-
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       }
-
-       return 0;
-}
-
-/**
- * _scsih_slave_destroy - device destroy routine
- * @sdev: scsi device struct
- *
- * Returns nothing.
- */
-static void
-_scsih_slave_destroy(struct scsi_device *sdev)
-{
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct scsi_target *starget;
-       struct Scsi_Host *shost;
-       struct MPT2SAS_ADAPTER *ioc;
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       if (!sdev->hostdata)
-               return;
-
-       starget = scsi_target(sdev);
-       sas_target_priv_data = starget->hostdata;
-       sas_target_priv_data->num_luns--;
-
-       shost = dev_to_shost(&starget->dev);
-       ioc = shost_priv(shost);
-
-       if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = __mpt2sas_get_sdev_from_target(ioc,
-                               sas_target_priv_data);
-               if (sas_device && !sas_target_priv_data->num_luns)
-                       sas_device->starget = NULL;
-
-               if (sas_device)
-                       sas_device_put(sas_device);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       }
-
-       kfree(sdev->hostdata);
-       sdev->hostdata = NULL;
-}
-
-/**
- * _scsih_display_sata_capabilities - sata capabilities
- * @ioc: per adapter object
- * @handle: device handle
- * @sdev: scsi device struct
- */
-static void
-_scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
-       u16 handle, struct scsi_device *sdev)
-{
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       u32 ioc_status;
-       u16 flags;
-       u32 device_info;
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       flags = le16_to_cpu(sas_device_pg0.Flags);
-       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-
-       sdev_printk(KERN_INFO, sdev,
-           "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
-           "sw_preserve(%s)\n",
-           (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
-           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
-           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
-           "n",
-           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
-           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
-           (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
-}
-
-/**
- * _scsih_is_raid - return boolean indicating device is raid volume
- * @dev the device struct object
- */
-static int
-_scsih_is_raid(struct device *dev)
-{
-       struct scsi_device *sdev = to_scsi_device(dev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
-
-       if (ioc->is_warpdrive)
-               return 0;
-       return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
-}
-
-/**
- * _scsih_get_resync - get raid volume resync percent complete
- * @dev the device struct object
- */
-static void
-_scsih_get_resync(struct device *dev)
-{
-       struct scsi_device *sdev = to_scsi_device(dev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
-       static struct _raid_device *raid_device;
-       unsigned long flags;
-       Mpi2RaidVolPage0_t vol_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u32 volume_status_flags;
-       u8 percent_complete;
-       u16 handle;
-
-       percent_complete = 0;
-       handle = 0;
-       if (ioc->is_warpdrive)
-               goto out;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
-           sdev->channel);
-       if (raid_device) {
-               handle = raid_device->handle;
-               percent_complete = raid_device->percent_complete;
-       }
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
-       if (!handle)
-               goto out;
-
-       if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
-            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
-            sizeof(Mpi2RaidVolPage0_t))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               percent_complete = 0;
-               goto out;
-       }
-
-       volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
-       if (!(volume_status_flags &
-           MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
-               percent_complete = 0;
-
- out:
-       raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
-}
-
-/**
- * _scsih_get_state - get raid volume level
- * @dev the device struct object
- */
-static void
-_scsih_get_state(struct device *dev)
-{
-       struct scsi_device *sdev = to_scsi_device(dev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host);
-       static struct _raid_device *raid_device;
-       unsigned long flags;
-       Mpi2RaidVolPage0_t vol_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u32 volstate;
-       enum raid_state state = RAID_STATE_UNKNOWN;
-       u16 handle = 0;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
-           sdev->channel);
-       if (raid_device)
-               handle = raid_device->handle;
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
-       if (!raid_device)
-               goto out;
-
-       if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
-            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
-            sizeof(Mpi2RaidVolPage0_t))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-
-       volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
-       if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
-               state = RAID_STATE_RESYNCING;
-               goto out;
-       }
-
-       switch (vol_pg0.VolumeState) {
-       case MPI2_RAID_VOL_STATE_OPTIMAL:
-       case MPI2_RAID_VOL_STATE_ONLINE:
-               state = RAID_STATE_ACTIVE;
-               break;
-       case  MPI2_RAID_VOL_STATE_DEGRADED:
-               state = RAID_STATE_DEGRADED;
-               break;
-       case MPI2_RAID_VOL_STATE_FAILED:
-       case MPI2_RAID_VOL_STATE_MISSING:
-               state = RAID_STATE_OFFLINE;
-               break;
-       }
- out:
-       raid_set_state(mpt2sas_raid_template, dev, state);
-}
-
-/**
- * _scsih_set_level - set raid level
- * @sdev: scsi device struct
- * @volume_type: volume type
- */
-static void
-_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
-{
-       enum raid_level level = RAID_LEVEL_UNKNOWN;
-
-       switch (volume_type) {
-       case MPI2_RAID_VOL_TYPE_RAID0:
-               level = RAID_LEVEL_0;
-               break;
-       case MPI2_RAID_VOL_TYPE_RAID10:
-               level = RAID_LEVEL_10;
-               break;
-       case MPI2_RAID_VOL_TYPE_RAID1E:
-               level = RAID_LEVEL_1E;
-               break;
-       case MPI2_RAID_VOL_TYPE_RAID1:
-               level = RAID_LEVEL_1;
-               break;
-       }
-
-       raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level);
-}
-
-/**
- * _scsih_get_volume_capabilities - volume capabilities
- * @ioc: per adapter object
- * @sas_device: the raid_device object
- *
- * Returns 0 for success, else 1
- */
-static int
-_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
-    struct _raid_device *raid_device)
-{
-       Mpi2RaidVolPage0_t *vol_pg0;
-       Mpi2RaidPhysDiskPage0_t pd_pg0;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 sz;
-       u8 num_pds;
-
-       if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
-           &num_pds)) || !num_pds) {
-               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
-                   __func__));
-               return 1;
-       }
-
-       raid_device->num_pds = num_pds;
-       sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
-           sizeof(Mpi2RaidVol0PhysDisk_t));
-       vol_pg0 = kzalloc(sz, GFP_KERNEL);
-       if (!vol_pg0) {
-               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
-                   __func__));
-               return 1;
-       }
-
-       if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
-            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
-               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                   "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
-                   __func__));
-               kfree(vol_pg0);
-               return 1;
-       }
-
-       raid_device->volume_type = vol_pg0->VolumeType;
-
-       /* figure out what the underlying devices are by
-        * obtaining the device_info bits for the 1st device
-        */
-       if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
-           &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
-           vol_pg0->PhysDisk[0].PhysDiskNum))) {
-               if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
-                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
-                   le16_to_cpu(pd_pg0.DevHandle)))) {
-                       raid_device->device_info =
-                           le32_to_cpu(sas_device_pg0.DeviceInfo);
-               }
-       }
-
-       kfree(vol_pg0);
-       return 0;
-}
-/**
- * _scsih_disable_ddio - Disable direct I/O for all the volumes
- * @ioc: per adapter object
- */
-static void
-_scsih_disable_ddio(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2RaidVolPage1_t vol_pg1;
-       Mpi2ConfigReply_t mpi_reply;
-       struct _raid_device *raid_device;
-       u16 handle;
-       u16 ioc_status;
-       unsigned long flags;
-
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
-           &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
-               handle = le16_to_cpu(vol_pg1.DevHandle);
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-               if (raid_device)
-                       raid_device->direct_io_enabled = 0;
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       }
-       return;
-}
-
-
-/**
- * _scsih_get_num_volumes - Get number of volumes in the ioc
- * @ioc: per adapter object
- */
-static u8
-_scsih_get_num_volumes(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2RaidVolPage1_t vol_pg1;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 handle;
-       u8 vol_cnt = 0;
-       u16 ioc_status;
-
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
-           &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
-                       break;
-               vol_cnt++;
-               handle = le16_to_cpu(vol_pg1.DevHandle);
-       }
-       return vol_cnt;
-}
-
-
-/**
- * _scsih_init_warpdrive_properties - Set properties for warpdrive direct I/O.
- * @ioc: per adapter object
- * @raid_device: the raid_device object
- */
-static void
-_scsih_init_warpdrive_properties(struct MPT2SAS_ADAPTER *ioc,
-       struct _raid_device *raid_device)
-{
-       Mpi2RaidVolPage0_t *vol_pg0;
-       Mpi2RaidPhysDiskPage0_t pd_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 sz;
-       u8 num_pds, count;
-       unsigned long stripe_sz, block_sz;
-       u8 stripe_exp, block_exp;
-       u64 dev_max_lba;
-
-       if (!ioc->is_warpdrive)
-               return;
-
-       if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_EXPOSE_ALL_DISKS) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "globally as drives are exposed\n", ioc->name);
-               return;
-       }
-       if (_scsih_get_num_volumes(ioc) > 1) {
-               _scsih_disable_ddio(ioc);
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "globally as number of drives > 1\n", ioc->name);
-               return;
-       }
-       if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
-           &num_pds)) || !num_pds) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "Failure in computing number of drives\n", ioc->name);
-               return;
-       }
-
-       sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
-           sizeof(Mpi2RaidVol0PhysDisk_t));
-       vol_pg0 = kzalloc(sz, GFP_KERNEL);
-       if (!vol_pg0) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "Memory allocation failure for RVPG0\n", ioc->name);
-               return;
-       }
-
-       if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
-            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "Failure in retrieving RVPG0\n", ioc->name);
-               kfree(vol_pg0);
-               return;
-       }
-
-       /*
-        * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
-        * assumed for WARPDRIVE, disable direct I/O
-        */
-       if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
-               printk(MPT2SAS_WARN_FMT "WarpDrive : Direct IO is disabled "
-                   "for the drive with handle(0x%04x): num_mem=%d, "
-                   "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
-                   num_pds, MPT_MAX_WARPDRIVE_PDS);
-               kfree(vol_pg0);
-               return;
-       }
-       for (count = 0; count < num_pds; count++) {
-               if (mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
-                   &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
-                   vol_pg0->PhysDisk[count].PhysDiskNum) ||
-                    le16_to_cpu(pd_pg0.DevHandle) ==
-                   MPT2SAS_INVALID_DEVICE_HANDLE) {
-                       printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
-                           "disabled for the drive with handle(0x%04x) member"
-                           "handle retrieval failed for member number=%d\n",
-                           ioc->name, raid_device->handle,
-                           vol_pg0->PhysDisk[count].PhysDiskNum);
-                       goto out_error;
-               }
-               /* Disable direct I/O if member drive lba exceeds 4 bytes */
-               dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA);
-               if (dev_max_lba >> 32) {
-                       printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is "
-                           "disabled for the drive with handle(0x%04x) member"
-                           "handle (0x%04x) unsupported max lba 0x%016llx\n",
-                           ioc->name, raid_device->handle,
-                           le16_to_cpu(pd_pg0.DevHandle),
-                           (unsigned long long)dev_max_lba);
-                       goto out_error;
-               }
-
-               raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
-       }
-
-       /*
-        * Assumption for WD: Direct I/O is not supported if the volume is
-        * not RAID0
-        */
-       if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "for the drive with handle(0x%04x): type=%d, "
-                   "s_sz=%uK, blk_size=%u\n", ioc->name,
-                   raid_device->handle, raid_device->volume_type,
-                   (le32_to_cpu(vol_pg0->StripeSize) *
-                   le16_to_cpu(vol_pg0->BlockSize)) / 1024,
-                   le16_to_cpu(vol_pg0->BlockSize));
-               goto out_error;
-       }
-
-       stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
-       stripe_exp = find_first_bit(&stripe_sz, 32);
-       if (stripe_exp == 32) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-               "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
-                   ioc->name, raid_device->handle,
-                   (le32_to_cpu(vol_pg0->StripeSize) *
-                   le16_to_cpu(vol_pg0->BlockSize)) / 1024);
-               goto out_error;
-       }
-       raid_device->stripe_exponent = stripe_exp;
-       block_sz = le16_to_cpu(vol_pg0->BlockSize);
-       block_exp = find_first_bit(&block_sz, 16);
-       if (block_exp == 16) {
-               printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is disabled "
-                   "for the drive with handle(0x%04x) invalid block sz %u\n",
-                   ioc->name, raid_device->handle,
-                   le16_to_cpu(vol_pg0->BlockSize));
-               goto out_error;
-       }
-       raid_device->block_exponent = block_exp;
-       raid_device->direct_io_enabled = 1;
-
-       printk(MPT2SAS_INFO_FMT "WarpDrive : Direct IO is Enabled for the drive"
-           " with handle(0x%04x)\n", ioc->name, raid_device->handle);
-       /*
-        * WARPDRIVE: Though the following fields are not used for direct IO,
-        * stored for future purpose:
-        */
-       raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
-       raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
-       raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
-
-
-       kfree(vol_pg0);
-       return;
-
-out_error:
-       raid_device->direct_io_enabled = 0;
-       for (count = 0; count < num_pds; count++)
-               raid_device->pd_handle[count] = 0;
-       kfree(vol_pg0);
-       return;
-}
-
-/**
- * _scsih_enable_tlr - setting TLR flags
- * @ioc: per adapter object
- * @sdev: scsi device struct
- *
- * Enabling Transaction Layer Retries for tape devices when
- * vpd page 0x90 is present
- *
- */
-static void
-_scsih_enable_tlr(struct MPT2SAS_ADAPTER *ioc, struct scsi_device *sdev)
-{
-       /* only for TAPE */
-       if (sdev->type != TYPE_TAPE)
-               return;
-
-       if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
-               return;
-
-       sas_enable_tlr(sdev);
-       sdev_printk(KERN_INFO, sdev, "TLR %s\n",
-           sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
-       return;
-
-}
-
-/**
- * _scsih_slave_configure - device configure routine.
- * @sdev: scsi device struct
- *
- * Returns 0 if ok. Any other return is assumed to be an error and
- * the device is ignored.
- */
-static int
-_scsih_slave_configure(struct scsi_device *sdev)
-{
-       struct Scsi_Host *shost = sdev->host;
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct _sas_device *sas_device;
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       int qdepth;
-       u8 ssp_target = 0;
-       char *ds = "";
-       char *r_level = "";
-       u16 handle, volume_handle = 0;
-       u64 volume_wwid = 0;
-
-       qdepth = 1;
-       sas_device_priv_data = sdev->hostdata;
-       sas_device_priv_data->configured_lun = 1;
-       sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
-       sas_target_priv_data = sas_device_priv_data->sas_target;
-       handle = sas_target_priv_data->handle;
-
-       /* raid volume handling */
-       if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
-
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-               if (!raid_device) {
-                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
-                           __LINE__, __func__));
-                       return 1;
-               }
-
-               if (_scsih_get_volume_capabilities(ioc, raid_device)) {
-                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
-                           __LINE__, __func__));
-                       return 1;
-               }
-               /*
-                * WARPDRIVE: Initialize the required data for Direct IO
-                */
-               _scsih_init_warpdrive_properties(ioc, raid_device);
-
-               /* RAID Queue Depth Support
-                * IS volume = underlying qdepth of drive type, either
-                *    MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
-                * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
-                */
-               if (raid_device->device_info &
-                   MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
-                       qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
-                       ds = "SSP";
-               } else {
-                       qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
-                        if (raid_device->device_info &
-                           MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
-                               ds = "SATA";
-                       else
-                               ds = "STP";
-               }
-
-               switch (raid_device->volume_type) {
-               case MPI2_RAID_VOL_TYPE_RAID0:
-                       r_level = "RAID0";
-                       break;
-               case MPI2_RAID_VOL_TYPE_RAID1E:
-                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
-                       if (ioc->manu_pg10.OEMIdentifier &&
-                           (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
-                           MFG10_GF0_R10_DISPLAY) &&
-                           !(raid_device->num_pds % 2))
-                               r_level = "RAID10";
-                       else
-                               r_level = "RAID1E";
-                       break;
-               case MPI2_RAID_VOL_TYPE_RAID1:
-                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
-                       r_level = "RAID1";
-                       break;
-               case MPI2_RAID_VOL_TYPE_RAID10:
-                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
-                       r_level = "RAID10";
-                       break;
-               case MPI2_RAID_VOL_TYPE_UNKNOWN:
-               default:
-                       qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
-                       r_level = "RAIDX";
-                       break;
-               }
-
-               if (!ioc->hide_ir_msg)
-                       sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
-                           "wwid(0x%016llx), pd_count(%d), type(%s)\n",
-                           r_level, raid_device->handle,
-                           (unsigned long long)raid_device->wwid,
-                           raid_device->num_pds, ds);
-               _scsih_change_queue_depth(sdev, qdepth);
-               /* raid transport support */
-               if (!ioc->is_warpdrive)
-                       _scsih_set_level(sdev, raid_device->volume_type);
-               return 0;
-       }
-
-       /* non-raid handling */
-       if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               if (mpt2sas_config_get_volume_handle(ioc, handle,
-                   &volume_handle)) {
-                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name,
-                           __FILE__, __LINE__, __func__));
-                       return 1;
-               }
-               if (volume_handle && mpt2sas_config_get_volume_wwid(ioc,
-                   volume_handle, &volume_wwid)) {
-                       dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name,
-                           __FILE__, __LINE__, __func__));
-                       return 1;
-               }
-       }
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-          sas_device_priv_data->sas_target->sas_address);
-       if (!sas_device) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               dfailprintk(ioc, printk(MPT2SAS_WARN_FMT
-                       "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
-                       __LINE__, __func__));
-               return 1;
-       }
-       sas_device->volume_handle = volume_handle;
-       sas_device->volume_wwid = volume_wwid;
-       if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
-               qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
-               ssp_target = 1;
-               ds = "SSP";
-       } else {
-               qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
-               if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
-                       ds = "STP";
-               else if (sas_device->device_info &
-                   MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
-                       ds = "SATA";
-       }
-       sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
-           "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
-           ds, sas_device->handle,
-           (unsigned long long)sas_device->sas_address,
-           sas_device->phy,
-           (unsigned long long)sas_device->device_name);
-       sdev_printk(KERN_INFO, sdev, "%s: "
-           "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
-           (unsigned long long) sas_device->enclosure_logical_id,
-           sas_device->slot);
-
-       sas_device_put(sas_device);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (!ssp_target)
-               _scsih_display_sata_capabilities(ioc, handle, sdev);
-
-       _scsih_change_queue_depth(sdev, qdepth);
-
-       if (ssp_target) {
-               sas_read_port_mode_page(sdev);
-               _scsih_enable_tlr(ioc, sdev);
-       }
-
-       return 0;
-}
-
-/**
- * _scsih_bios_param - fetch head, sector, cylinder info for a disk
- * @sdev: scsi device struct
- * @bdev: pointer to block device context
- * @capacity: device size (in 512 byte sectors)
- * @params: three element array to place output:
- *              params[0] number of heads (max 255)
- *              params[1] number of sectors (max 63)
- *              params[2] number of cylinders
- *
- * Return nothing.
- */
-static int
-_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-    sector_t capacity, int params[])
-{
-       int             heads;
-       int             sectors;
-       sector_t        cylinders;
-       ulong           dummy;
-
-       heads = 64;
-       sectors = 32;
-
-       dummy = heads * sectors;
-       cylinders = capacity;
-       sector_div(cylinders, dummy);
-
-       /*
-        * Handle extended translation size for logical drives
-        * > 1Gb
-        */
-       if ((ulong)capacity >= 0x200000) {
-               heads = 255;
-               sectors = 63;
-               dummy = heads * sectors;
-               cylinders = capacity;
-               sector_div(cylinders, dummy);
-       }
-
-       /* return result */
-       params[0] = heads;
-       params[1] = sectors;
-       params[2] = cylinders;
-
-       return 0;
-}
-
-/**
- * _scsih_response_code - translation of device response code
- * @ioc: per adapter object
- * @response_code: response code returned by the device
- *
- * Return nothing.
- */
-static void
-_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
-{
-       char *desc;
-
-       switch (response_code) {
-       case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
-               desc = "task management request completed";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
-               desc = "invalid frame";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
-               desc = "task management request not supported";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
-               desc = "task management request failed";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
-               desc = "task management request succeeded";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
-               desc = "invalid lun";
-               break;
-       case 0xA:
-               desc = "overlapped tag attempted";
-               break;
-       case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
-               desc = "task queued, however not sent to target";
-               break;
-       default:
-               desc = "unknown";
-               break;
-       }
-       printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
-               ioc->name, response_code, desc);
-}
-
-/**
- * _scsih_tm_done - tm 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: none.
- *
- * The callback handler when using scsih_issue_tm.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-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 1;
-       if (ioc->tm_cmds.smid != smid)
-               return 1;
-       mpt2sas_base_flush_reply_queues(ioc);
-       ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
-       mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (mpi_reply) {
-               memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
-               ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
-       }
-       ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
-       complete(&ioc->tm_cmds.done);
-       return 1;
-}
-
-/**
- * mpt2sas_scsih_set_tm_flag - set per target tm_busy
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During taskmangement request, we need to freeze the device queue.
- */
-void
-mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-       u8 skip = 0;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               if (skip)
-                       continue;
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (sas_device_priv_data->sas_target->handle == handle) {
-                       sas_device_priv_data->sas_target->tm_busy = 1;
-                       skip = 1;
-                       ioc->ignore_loginfos = 1;
-               }
-       }
-}
-
-/**
- * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During taskmangement request, we need to freeze the device queue.
- */
-void
-mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-       u8 skip = 0;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               if (skip)
-                       continue;
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (sas_device_priv_data->sas_target->handle == handle) {
-                       sas_device_priv_data->sas_target->tm_busy = 0;
-                       skip = 1;
-                       ioc->ignore_loginfos = 0;
-               }
-       }
-}
-
-
-/**
- * mpt2sas_scsih_issue_tm - main routine for sending tm requests
- * @ioc: per adapter struct
- * @device_handle: device handle
- * @channel: the channel assigned by the OS
- * @id: the id assigned by the OS
- * @lun: lun number
- * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
- * @smid_task: smid assigned to the task
- * @timeout: timeout in seconds
- * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
- * Context: user
- *
- * A generic API for sending task management requests to firmware.
- *
- * The callback index is set inside `ioc->tm_cb_idx`.
- *
- * Return SUCCESS or FAILED.
- */
-int
-mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint channel,
-    uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
-       enum mutex_type m_type)
-{
-       Mpi2SCSITaskManagementRequest_t *mpi_request;
-       Mpi2SCSITaskManagementReply_t *mpi_reply;
-       u16 smid = 0;
-       u32 ioc_state;
-       unsigned long timeleft;
-       struct scsiio_tracker *scsi_lookup = NULL;
-       int rc;
-
-       if (m_type == TM_MUTEX_ON)
-               mutex_lock(&ioc->tm_cmds.mutex);
-       if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
-                   __func__, ioc->name);
-               rc = FAILED;
-               goto err_out;
-       }
-
-       if (ioc->shost_recovery || ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               rc = FAILED;
-               goto err_out;
-       }
-
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
-       if (ioc_state & MPI2_DOORBELL_USED) {
-               dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "unexpected doorbell "
-                   "active!\n", ioc->name));
-               rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-               rc = (!rc) ? SUCCESS : FAILED;
-               goto err_out;
-       }
-
-       if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
-               mpt2sas_base_fault_info(ioc, ioc_state &
-                   MPI2_DOORBELL_DATA_MASK);
-               rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-               rc = (!rc) ? SUCCESS : FAILED;
-               goto err_out;
-       }
-
-       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__);
-               rc = FAILED;
-               goto err_out;
-       }
-
-       if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-               scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
-
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
-           " 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;
-       memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
-       memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
-       mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
-       mpi_request->DevHandle = cpu_to_le16(handle);
-       mpi_request->TaskType = type;
-       mpi_request->TaskMID = cpu_to_le16(smid_task);
-       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);
-       timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
-       if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SCSITaskManagementRequest_t)/4);
-               if (!(ioc->tm_cmds.status & MPT2_CMD_RESET)) {
-                       rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                           FORCE_BIG_HAMMER);
-                       rc = (!rc) ? SUCCESS : FAILED;
-                       ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-                       mpt2sas_scsih_clear_tm_flag(ioc, handle);
-                       goto err_out;
-               }
-       }
-
-       if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
-               mpi_reply = ioc->tm_cmds.reply;
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
-                   "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
-                   le32_to_cpu(mpi_reply->IOCLogInfo),
-                   le32_to_cpu(mpi_reply->TerminationCount)));
-               if (ioc->logging_level & MPT_DEBUG_TM) {
-                       _scsih_response_code(ioc, mpi_reply->ResponseCode);
-                       if (mpi_reply->IOCStatus)
-                               _debug_dump_mf(mpi_request,
-                                   sizeof(Mpi2SCSITaskManagementRequest_t)/4);
-               }
-       }
-
-       switch (type) {
-       case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
-               rc = SUCCESS;
-               if (scsi_lookup->scmd == NULL)
-                       break;
-               rc = FAILED;
-               break;
-
-       case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
-               if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
-                       rc = FAILED;
-               else
-                       rc = SUCCESS;
-               break;
-
-       case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
-       case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
-               if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
-                       rc = FAILED;
-               else
-                       rc = SUCCESS;
-               break;
-       case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
-               rc = SUCCESS;
-               break;
-       default:
-               rc = FAILED;
-               break;
-       }
-
-       mpt2sas_scsih_clear_tm_flag(ioc, handle);
-       ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
-       if (m_type == TM_MUTEX_ON)
-               mutex_unlock(&ioc->tm_cmds.mutex);
-
-       return rc;
-
- err_out:
-       if (m_type == TM_MUTEX_ON)
-               mutex_unlock(&ioc->tm_cmds.mutex);
-       return rc;
-}
-
-/**
- * _scsih_tm_display_info - displays info about the device
- * @ioc: per adapter struct
- * @scmd: pointer to scsi command object
- *
- * Called by task management callback handlers.
- */
-static void
-_scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
-{
-       struct scsi_target *starget = scmd->device->sdev_target;
-       struct MPT2SAS_TARGET *priv_target = starget->hostdata;
-       struct _sas_device *sas_device = NULL;
-       unsigned long flags;
-       char *device_str = NULL;
-
-       if (!priv_target)
-               return;
-       if (ioc->hide_ir_msg)
-               device_str = "WarpDrive";
-       else
-               device_str = "volume";
-
-       scsi_print_command(scmd);
-       if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
-               starget_printk(KERN_INFO, starget, "%s handle(0x%04x), "
-                   "%s wwid(0x%016llx)\n", device_str, priv_target->handle,
-                   device_str, (unsigned long long)priv_target->sas_address);
-       } else {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = __mpt2sas_get_sdev_from_target(ioc, priv_target);
-               if (sas_device) {
-                       if (priv_target->flags &
-                           MPT_TARGET_FLAGS_RAID_COMPONENT) {
-                               starget_printk(KERN_INFO, starget,
-                                   "volume handle(0x%04x), "
-                                   "volume wwid(0x%016llx)\n",
-                                   sas_device->volume_handle,
-                                  (unsigned long long)sas_device->volume_wwid);
-                       }
-                       starget_printk(KERN_INFO, starget,
-                           "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
-                           sas_device->handle,
-                           (unsigned long long)sas_device->sas_address,
-                           sas_device->phy);
-                       starget_printk(KERN_INFO, starget,
-                           "enclosure_logical_id(0x%016llx), slot(%d)\n",
-                          (unsigned long long)sas_device->enclosure_logical_id,
-                           sas_device->slot);
-
-                       sas_device_put(sas_device);
-               }
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       }
-}
-
-/**
- * _scsih_abort - eh threads main abort routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_abort(struct scsi_cmnd *scmd)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       u16 smid;
-       u16 handle;
-       int r;
-
-       sdev_printk(KERN_INFO, scmd->device, "attempting task abort! "
-           "scmd(%p)\n", scmd);
-       _scsih_tm_display_info(ioc, scmd);
-
-       sas_device_priv_data = scmd->device->hostdata;
-       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
-               sdev_printk(KERN_INFO, scmd->device, "device been deleted! "
-                   "scmd(%p)\n", scmd);
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               r = SUCCESS;
-               goto out;
-       }
-
-       /* search for the command */
-       smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
-       if (!smid) {
-               scmd->result = DID_RESET << 16;
-               r = SUCCESS;
-               goto out;
-       }
-
-       /* for hidden raid components and volumes this is not supported */
-       if (sas_device_priv_data->sas_target->flags &
-           MPT_TARGET_FLAGS_RAID_COMPONENT ||
-           sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
-               scmd->result = DID_RESET << 16;
-               r = FAILED;
-               goto out;
-       }
-
-       mpt2sas_halt_firmware(ioc);
-
-       handle = sas_device_priv_data->sas_target->handle;
-       r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
-           scmd->device->id, scmd->device->lun,
-           MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON);
-
- out:
-       sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
-           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-       return r;
-}
-
-/**
- * _scsih_dev_reset - eh threads main device reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_dev_reset(struct scsi_cmnd *scmd)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct _sas_device *sas_device = NULL;
-       u16     handle;
-       int r;
-
-       struct scsi_target *starget = scmd->device->sdev_target;
-       struct MPT2SAS_TARGET *target_priv_data = starget->hostdata;
-
-       starget_printk(KERN_INFO, starget, "attempting device reset! "
-           "scmd(%p)\n", scmd);
-       _scsih_tm_display_info(ioc, scmd);
-
-       sas_device_priv_data = scmd->device->hostdata;
-       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
-               starget_printk(KERN_INFO, starget, "device been deleted! "
-                   "scmd(%p)\n", scmd);
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               r = SUCCESS;
-               goto out;
-       }
-
-       /* for hidden raid components obtain the volume_handle */
-       handle = 0;
-       if (sas_device_priv_data->sas_target->flags &
-           MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               sas_device = mpt2sas_get_sdev_from_target(ioc,
-                               target_priv_data);
-               if (sas_device)
-                       handle = sas_device->volume_handle;
-       } else
-               handle = sas_device_priv_data->sas_target->handle;
-
-       if (!handle) {
-               scmd->result = DID_RESET << 16;
-               r = FAILED;
-               goto out;
-       }
-
-       r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
-           scmd->device->id, scmd->device->lun,
-           MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON);
-
- out:
-       sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
-           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
-       if (sas_device)
-               sas_device_put(sas_device);
-
-       return r;
-}
-
-/**
- * _scsih_target_reset - eh threads main target reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_target_reset(struct scsi_cmnd *scmd)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct _sas_device *sas_device = NULL;
-       u16     handle;
-       int r;
-       struct scsi_target *starget = scmd->device->sdev_target;
-       struct MPT2SAS_TARGET *target_priv_data = starget->hostdata;
-
-       starget_printk(KERN_INFO, starget, "attempting target reset! "
-           "scmd(%p)\n", scmd);
-       _scsih_tm_display_info(ioc, scmd);
-
-       sas_device_priv_data = scmd->device->hostdata;
-       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
-               starget_printk(KERN_INFO, starget, "target been deleted! "
-                   "scmd(%p)\n", scmd);
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               r = SUCCESS;
-               goto out;
-       }
-
-       /* for hidden raid components obtain the volume_handle */
-       handle = 0;
-       if (sas_device_priv_data->sas_target->flags &
-           MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               sas_device = mpt2sas_get_sdev_from_target(ioc,
-                               target_priv_data);
-               if (sas_device)
-                       handle = sas_device->volume_handle;
-       } else
-               handle = sas_device_priv_data->sas_target->handle;
-
-       if (!handle) {
-               scmd->result = DID_RESET << 16;
-               r = FAILED;
-               goto out;
-       }
-
-       r = mpt2sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
-           scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
-           30, TM_MUTEX_ON);
-
- out:
-       starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
-           ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
-       if (sas_device)
-               sas_device_put(sas_device);
-
-       return r;
-}
-
-/**
- * _scsih_host_reset - eh threads main host reset routine
- * @scmd: pointer to scsi command object
- *
- * Returns SUCCESS if command aborted else FAILED
- */
-static int
-_scsih_host_reset(struct scsi_cmnd *scmd)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
-       int r, retval;
-
-       printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
-           ioc->name, scmd);
-       scsi_print_command(scmd);
-
-       if (ioc->is_driver_loading) {
-               printk(MPT2SAS_INFO_FMT "Blocking the host reset\n",
-                                                         ioc->name);
-               r = FAILED;
-               goto out;
-       }
-
-       retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-           FORCE_BIG_HAMMER);
-       r = (retval < 0) ? FAILED : SUCCESS;
-
- out:
-       printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
-           ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-
-       return r;
-}
-
-/**
- * _scsih_fw_event_add - insert and queue up fw_event
- * @ioc: per adapter object
- * @fw_event: object describing the event
- * Context: This function will acquire ioc->fw_event_lock.
- *
- * This adds the firmware event object into link list, then queues it up to
- * be processed from user context.
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
-{
-       unsigned long flags;
-
-       if (ioc->firmware_event_thread == NULL)
-               return;
-
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       fw_event_work_get(fw_event);
-       list_add_tail(&fw_event->list, &ioc->fw_event_list);
-       INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work);
-       fw_event_work_get(fw_event);
-       queue_delayed_work(ioc->firmware_event_thread,
-           &fw_event->delayed_work, 0);
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_fw_event_del_from_list - delete fw_event from the list
- * @ioc: per adapter object
- * @fw_event: object describing the event
- * Context: This function will acquire ioc->fw_event_lock.
- *
- * If the fw_event is on the fw_event_list, remove it and do a put.
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_del_from_list(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
-    *fw_event)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       if (!list_empty(&fw_event->list)) {
-               list_del_init(&fw_event->list);
-               fw_event_work_put(fw_event);
-       }
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_error_recovery_delete_devices - remove devices not responding
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct fw_event_work *fw_event;
-
-       if (ioc->is_driver_loading)
-               return;
-
-       fw_event = alloc_fw_event_work(0);
-       if (!fw_event)
-               return;
-
-       fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
-       fw_event->ioc = ioc;
-       _scsih_fw_event_add(ioc, fw_event);
-       fw_event_work_put(fw_event);
-}
-
-/**
- * mpt2sas_port_enable_complete - port enable completed (fake event)
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-void
-mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct fw_event_work *fw_event;
-
-       fw_event = alloc_fw_event_work(0);
-       if (!fw_event)
-               return;
-       fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE;
-       fw_event->ioc = ioc;
-       _scsih_fw_event_add(ioc, fw_event);
-       fw_event_work_put(fw_event);
-}
-
-static struct fw_event_work *dequeue_next_fw_event(struct MPT2SAS_ADAPTER *ioc)
-{
-       unsigned long flags;
-       struct fw_event_work *fw_event = NULL;
-
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       if (!list_empty(&ioc->fw_event_list)) {
-               fw_event = list_first_entry(&ioc->fw_event_list,
-                               struct fw_event_work, list);
-               list_del_init(&fw_event->list);
-       }
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-
-       return fw_event;
-}
-
-/**
- * _scsih_fw_event_cleanup_queue - cleanup event queue
- * @ioc: per adapter object
- *
- * Walk the firmware event queue, either killing timers, or waiting
- * for outstanding events to complete
- *
- * Return nothing.
- */
-static void
-_scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct fw_event_work *fw_event;
-
-       if (list_empty(&ioc->fw_event_list) ||
-            !ioc->firmware_event_thread || in_interrupt())
-               return;
-
-       while ((fw_event = dequeue_next_fw_event(ioc))) {
-               /*
-                * Wait on the fw_event to complete. If this returns 1, then
-                * the event was never executed, and we need a put for the
-                * reference the delayed_work had on the fw_event.
-                *
-                * If it did execute, we wait for it to finish, and the put will
-                * happen from _firmware_event_work()
-                */
-               if (cancel_delayed_work_sync(&fw_event->delayed_work))
-                       fw_event_work_put(fw_event);
-
-               fw_event_work_put(fw_event);
-       }
-}
-
-/**
- * _scsih_ublock_io_all_device - unblock every device
- * @ioc: per adapter object
- *
- * change the device state from block to running
- */
-static void
-_scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (!sas_device_priv_data->block)
-                       continue;
-               sas_device_priv_data->block = 0;
-               dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
-                   "handle(0x%04x)\n",
-                   sas_device_priv_data->sas_target->handle));
-               scsi_internal_device_unblock(sdev, SDEV_RUNNING);
-       }
-}
-/**
- * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (!sas_device_priv_data->block)
-                       continue;
-               if (sas_device_priv_data->sas_target->sas_address ==
-                                                               sas_address) {
-                       dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
-                           MPT2SAS_INFO_FMT "SDEV_RUNNING: "
-                           "sas address(0x%016llx)\n", ioc->name,
-                               (unsigned long long)sas_address));
-                       sas_device_priv_data->block = 0;
-                       scsi_internal_device_unblock(sdev, SDEV_RUNNING);
-               }
-       }
-}
-
-/**
- * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_block_io_all_device(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (sas_device_priv_data->block)
-                       continue;
-               sas_device_priv_data->block = 1;
-               dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_blocked, "
-                   "handle(0x%04x)\n",
-                   sas_device_priv_data->sas_target->handle));
-               scsi_internal_device_block(sdev);
-       }
-}
-
-
-/**
- * _scsih_block_io_device - set the device state to SDEV_BLOCK
- * @ioc: per adapter object
- * @handle: device handle
- *
- * During device pull we need to appropiately set the sdev state.
- */
-static void
-_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data)
-                       continue;
-               if (sas_device_priv_data->block)
-                       continue;
-               if (sas_device_priv_data->sas_target->handle == handle) {
-                       dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
-                           MPT2SAS_INFO_FMT "SDEV_BLOCK: "
-                           "handle(0x%04x)\n", ioc->name, handle));
-                       sas_device_priv_data->block = 1;
-                       scsi_internal_device_block(sdev);
-               }
-       }
-}
-
-/**
- * _scsih_block_io_to_children_attached_to_ex
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- *
- * This routine set sdev state to SDEV_BLOCK for all devices
- * attached to this expander. This function called when expander is
- * pulled.
- */
-static void
-_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_node *sas_expander)
-{
-       struct _sas_port *mpt2sas_port;
-       struct _sas_device *sas_device;
-       struct _sas_node *expander_sibling;
-       unsigned long flags;
-
-       if (!sas_expander)
-               return;
-
-       list_for_each_entry(mpt2sas_port,
-          &sas_expander->sas_port_list, port_list) {
-               if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) {
-                       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-                       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-                                       mpt2sas_port->remote_identify.sas_address);
-                       if (sas_device) {
-                               set_bit(sas_device->handle,
-                                               ioc->blocking_handles);
-                               sas_device_put(sas_device);
-                       }
-                       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               }
-       }
-
-       list_for_each_entry(mpt2sas_port,
-          &sas_expander->sas_port_list, port_list) {
-
-               if (mpt2sas_port->remote_identify.device_type ==
-                   SAS_EDGE_EXPANDER_DEVICE ||
-                   mpt2sas_port->remote_identify.device_type ==
-                   SAS_FANOUT_EXPANDER_DEVICE) {
-                       expander_sibling =
-                           mpt2sas_scsih_expander_find_by_sas_address(
-                           ioc, mpt2sas_port->remote_identify.sas_address);
-                       _scsih_block_io_to_children_attached_to_ex(ioc,
-                           expander_sibling);
-               }
-       }
-}
-
-/**
- * _scsih_block_io_to_children_attached_directly
- * @ioc: per adapter object
- * @event_data: topology change event data
- *
- * This routine set sdev state to SDEV_BLOCK for all devices
- * direct attached during device pull.
- */
-static void
-_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
-       int i;
-       u16 handle;
-       u16 reason_code;
-       u8 phy_number;
-
-       for (i = 0; i < event_data->NumEntries; i++) {
-               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;
-               if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
-                       _scsih_block_io_device(ioc, handle);
-       }
-}
-
-/**
- * _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 protocol
- * with controller firmware.  This function will issue target reset
- * using high priority request queue.  It will send a sas iounit
- * control 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;
-       u16 smid;
-       struct _sas_device *sas_device = NULL;
-       struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
-       u64 sas_address = 0;
-       unsigned long flags;
-       struct _tr_list *delayed_tr;
-       u32 ioc_state;
-
-       if (ioc->remove_host) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
-                   "removed: handle(0x%04x)\n", __func__, ioc->name, handle));
-               return;
-       } else if (ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
-                   "error recovery: handle(0x%04x)\n", __func__, ioc->name,
-                   handle));
-               return;
-       }
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
-                  "operational: handle(0x%04x)\n", __func__, ioc->name,
-                  handle));
-               return;
-       }
-
-       /* if PD, then return */
-       if (test_bit(handle, ioc->pd_handles))
-               return;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (sas_device && sas_device->starget &&
-            sas_device->starget->hostdata) {
-               sas_target_priv_data = sas_device->starget->hostdata;
-               sas_target_priv_data->deleted = 1;
-               sas_address = sas_device->sas_address;
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (sas_target_priv_data) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
-               "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
-                       (unsigned long long)sas_address));
-               _scsih_ublock_io_device(ioc, sas_address);
-               sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
-       }
-
-       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)
-                       goto out;
-               INIT_LIST_HEAD(&delayed_tr->list);
-               delayed_tr->handle = handle;
-               list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "DELAYED:tr:handle(0x%04x), (open)\n",
-                   ioc->name, handle));
-               goto out;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
-           "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
-           ioc->tm_tr_cb_idx));
-       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;
-       mpt2sas_base_put_smid_hi_priority(ioc, smid);
-out:
-       if (sas_device)
-               sas_device_put(sas_device);
-}
-
-
-
-/**
- * _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 control completion routine.
- * This code is part of the code to initiate the device removal
- * handshake protocol 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)
-{
-       Mpi2SasIoUnitControlReply_t *mpi_reply =
-           mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       if (likely(mpi_reply)) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-               "sc_complete:handle(0x%04x), (open) "
-               "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
-               ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
-               le16_to_cpu(mpi_reply->IOCStatus),
-               le32_to_cpu(mpi_reply->IOCLogInfo)));
-       } else {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-       }
-       return 1;
-}
-
-/**
- * _scsih_tm_tr_volume_send - send target reset request for volumes
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt time.
- *
- * 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_volume_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       Mpi2SCSITaskManagementRequest_t *mpi_request;
-       u16 smid;
-       struct _tr_list *delayed_tr;
-
-       if (ioc->shost_recovery || ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
-                  "progress!\n", __func__, ioc->name));
-               return;
-       }
-
-       smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_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;
-               list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "DELAYED:tr:handle(0x%04x), (open)\n",
-                   ioc->name, handle));
-               return;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), "
-           "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid,
-           ioc->tm_tr_volume_cb_idx));
-       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;
-       mpt2sas_base_put_smid_hi_priority(ioc, smid);
-}
-
-/**
- * _scsih_tm_volume_tr_complete - target reset completion
- * @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.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-static u8
-_scsih_tm_volume_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid,
-    u8 msix_index, u32 reply)
-{
-       u16 handle;
-       Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
-       Mpi2SCSITaskManagementReply_t *mpi_reply =
-           mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
-       if (ioc->shost_recovery || ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host reset in "
-                  "progress!\n", __func__, ioc->name));
-               return 1;
-       }
-       if (unlikely(!mpi_reply)) {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return 1;
-       }
-       mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
-       handle = le16_to_cpu(mpi_request_tm->DevHandle);
-       if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
-               dewtprintk(ioc, printk("spurious interrupt: "
-                   "handle(0x%04x:0x%04x), smid(%d)!!!\n", handle,
-                   le16_to_cpu(mpi_reply->DevHandle), smid));
-               return 0;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-           "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
-           "loginfo(0x%08x), completed(%d)\n", ioc->name,
-           handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
-           le32_to_cpu(mpi_reply->IOCLogInfo),
-           le32_to_cpu(mpi_reply->TerminationCount)));
-
-       return _scsih_check_for_pending_tm(ioc, smid);
-}
-
-/**
- * _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 protocol with controller firmware.
- * It will send a sas iounit control 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)
-{
-       u16 handle;
-       Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
-       Mpi2SCSITaskManagementReply_t *mpi_reply =
-           mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       Mpi2SasIoUnitControlRequest_t *mpi_request;
-       u16 smid_sas_ctrl;
-       u32 ioc_state;
-
-       if (ioc->remove_host) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host has been "
-                  "removed\n", __func__, ioc->name));
-               return 1;
-       } else if (ioc->pci_error_recovery) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host in pci "
-                   "error recovery\n", __func__, ioc->name));
-               return 1;
-       }
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: host is not "
-                   "operational\n", __func__, ioc->name));
-               return 1;
-       }
-       if (unlikely(!mpi_reply)) {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return 1;
-       }
-       mpi_request_tm = mpt2sas_base_get_msg_frame(ioc, smid);
-       handle = le16_to_cpu(mpi_request_tm->DevHandle);
-       if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "spurious interrupt: "
-                   "handle(0x%04x:0x%04x), smid(%d)!!!\n", ioc->name, handle,
-                   le16_to_cpu(mpi_reply->DevHandle), smid));
-               return 0;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-           "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
-           "loginfo(0x%08x), completed(%d)\n", ioc->name,
-           handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
-           le32_to_cpu(mpi_reply->IOCLogInfo),
-           le32_to_cpu(mpi_reply->TerminationCount)));
-
-       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 1;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sc_send:handle(0x%04x), "
-           "(open), smid(%d), cb(%d)\n", ioc->name, handle, smid_sas_ctrl,
-           ioc->tm_sas_control_cb_idx));
-       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_request_tm->DevHandle;
-       mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl);
-
-       return _scsih_check_for_pending_tm(ioc, smid);
-}
-
-/**
- * _scsih_check_for_pending_tm - check for pending task management
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * This will check delayed target reset list, and feed the
- * next reqeust.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-static u8
-_scsih_check_for_pending_tm(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       struct _tr_list *delayed_tr;
-
-       if (!list_empty(&ioc->delayed_tr_volume_list)) {
-               delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
-                   struct _tr_list, list);
-               mpt2sas_base_free_smid(ioc, smid);
-               _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
-               list_del(&delayed_tr->list);
-               kfree(delayed_tr);
-               return 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);
-               _scsih_tm_tr_send(ioc, delayed_tr->handle);
-               list_del(&delayed_tr->list);
-               kfree(delayed_tr);
-               return 0;
-       }
-
-       return 1;
-}
-
-/**
- * _scsih_check_topo_delete_events - sanity check on topo events
- * @ioc: per adapter object
- * @event_data: the event data payload
- *
- * This routine added to better handle cable breaker.
- *
- * This handles the case where driver receives multiple expander
- * add and delete events in a single shot.  When there is a delete event
- * the routine will void any pending add events waiting in the event queue.
- *
- * Return nothing.
- */
-static void
-_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
-       struct fw_event_work *fw_event;
-       Mpi2EventDataSasTopologyChangeList_t *local_event_data;
-       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++) {
-               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) {
-               _scsih_block_io_to_children_attached_directly(ioc, event_data);
-               return;
-       }
-       if (event_data->ExpStatus ==
-           MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
-               /* put expander attached devices into blocking state */
-               spin_lock_irqsave(&ioc->sas_node_lock, flags);
-               sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
-                   expander_handle);
-               _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               do {
-                       handle = find_first_bit(ioc->blocking_handles,
-                           ioc->facts.MaxDevHandle);
-                       if (handle < ioc->facts.MaxDevHandle)
-                               _scsih_block_io_device(ioc, handle);
-               } while (test_and_clear_bit(handle, ioc->blocking_handles));
-       } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
-               _scsih_block_io_to_children_attached_directly(ioc, event_data);
-
-       if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
-               return;
-
-       /* mark ignore flag for pending events */
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
-               if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
-                   fw_event->ignore)
-                       continue;
-               local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
-                       fw_event->event_data;
-               if (local_event_data->ExpStatus ==
-                   MPI2_EVENT_SAS_TOPO_ES_ADDED ||
-                   local_event_data->ExpStatus ==
-                   MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
-                       if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
-                           expander_handle) {
-                               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                                   "setting ignoring flag\n", ioc->name));
-                               fw_event->ignore = 1;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-}
-
-/**
- * _scsih_set_volume_delete_flag - setting volume delete flag
- * @ioc: per adapter object
- * @handle: device handle
- *
- * This
- * Return nothing.
- */
-static void
-_scsih_set_volume_delete_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _raid_device *raid_device;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-       if (raid_device && raid_device->starget &&
-           raid_device->starget->hostdata) {
-               sas_target_priv_data =
-                   raid_device->starget->hostdata;
-               sas_target_priv_data->deleted = 1;
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "setting delete flag: handle(0x%04x), "
-                   "wwid(0x%016llx)\n", ioc->name, handle,
-                   (unsigned long long) raid_device->wwid));
-       }
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
- * @handle: input handle
- * @a: handle for volume a
- * @b: handle for volume b
- *
- * IR firmware only supports two raid volumes.  The purpose of this
- * routine is to set the volume handle in either a or b. When the given
- * input handle is non-zero, or when a and b have not been set before.
- */
-static void
-_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
-{
-       if (!handle || handle == *a || handle == *b)
-               return;
-       if (!*a)
-               *a = handle;
-       else if (!*b)
-               *b = handle;
-}
-
-/**
- * _scsih_check_ir_config_unhide_events - check for UNHIDE events
- * @ioc: per adapter object
- * @event_data: the event data payload
- * Context: interrupt time.
- *
- * This routine will send target reset to volume, followed by target
- * resets to the PDs. This is called when a PD has been removed, or
- * volume has been deleted or removed. When the target reset is sent
- * to volume, the PD target resets need to be queued to start upon
- * completion of the volume target reset.
- *
- * Return nothing.
- */
-static void
-_scsih_check_ir_config_unhide_events(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataIrConfigChangeList_t *event_data)
-{
-       Mpi2EventIrConfigElement_t *element;
-       int i;
-       u16 handle, volume_handle, a, b;
-       struct _tr_list *delayed_tr;
-
-       a = 0;
-       b = 0;
-
-       if (ioc->is_warpdrive)
-               return;
-
-       /* Volume Resets for Deleted or Removed */
-       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-       for (i = 0; i < event_data->NumElements; i++, element++) {
-               if (element->ReasonCode ==
-                   MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
-                   element->ReasonCode ==
-                   MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
-                       volume_handle = le16_to_cpu(element->VolDevHandle);
-                       _scsih_set_volume_delete_flag(ioc, volume_handle);
-                       _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
-               }
-       }
-
-       /* Volume Resets for UNHIDE events */
-       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-       for (i = 0; i < event_data->NumElements; i++, element++) {
-               if (le32_to_cpu(event_data->Flags) &
-                   MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
-                       continue;
-               if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
-                       volume_handle = le16_to_cpu(element->VolDevHandle);
-                       _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
-               }
-       }
-
-       if (a)
-               _scsih_tm_tr_volume_send(ioc, a);
-       if (b)
-               _scsih_tm_tr_volume_send(ioc, b);
-
-       /* PD target resets */
-       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-       for (i = 0; i < event_data->NumElements; i++, element++) {
-               if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
-                       continue;
-               handle = le16_to_cpu(element->PhysDiskDevHandle);
-               volume_handle = le16_to_cpu(element->VolDevHandle);
-               clear_bit(handle, ioc->pd_handles);
-               if (!volume_handle)
-                       _scsih_tm_tr_send(ioc, handle);
-               else if (volume_handle == a || volume_handle == b) {
-                       delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
-                       BUG_ON(!delayed_tr);
-                       INIT_LIST_HEAD(&delayed_tr->list);
-                       delayed_tr->handle = handle;
-                       list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
-                       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                           "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
-                           handle));
-               } else
-                       _scsih_tm_tr_send(ioc, handle);
-       }
-}
-
-
-/**
- * _scsih_check_volume_delete_events - set delete flag for volumes
- * @ioc: per adapter object
- * @event_data: the event data payload
- * Context: interrupt time.
- *
- * This will handle the case when the cable connected to entire volume is
- * pulled. We will take care of setting the deleted flag so normal IO will
- * not be sent.
- *
- * Return nothing.
- */
-static void
-_scsih_check_volume_delete_events(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataIrVolume_t *event_data)
-{
-       u32 state;
-
-       if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
-               return;
-       state = le32_to_cpu(event_data->NewValue);
-       if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
-           MPI2_RAID_VOL_STATE_FAILED)
-               _scsih_set_volume_delete_flag(ioc,
-                   le16_to_cpu(event_data->VolDevHandle));
-}
-
-/**
- * _scsih_temp_threshold_events - display temperature threshold exceeded events
- * @ioc: per adapter object
- * @event_data: the temp threshold event data
- * Context: interrupt time.
- *
- * Return nothing.
- */
-static void
-_scsih_temp_threshold_events(struct MPT2SAS_ADAPTER *ioc,
-       Mpi2EventDataTemperature_t *event_data)
-{
-       if (ioc->temp_sensors_count >= event_data->SensorNum) {
-               printk(MPT2SAS_ERR_FMT "Temperature Threshold flags %s%s%s%s"
-                 " exceeded for Sensor: %d !!!\n", ioc->name,
-                 ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
-                 ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
-                 ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
-                 ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
-                 event_data->SensorNum);
-               printk(MPT2SAS_ERR_FMT "Current Temp In Celsius: %d\n",
-                       ioc->name, event_data->CurrentTemperature);
-       }
-}
-
-/**
- * _scsih_flush_running_cmds - completing outstanding commands.
- * @ioc: per adapter object
- *
- * The flushing out of all pending scmd commands following host reset,
- * where all IO is dropped to the floor.
- *
- * Return nothing.
- */
-static void
-_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct scsi_cmnd *scmd;
-       u16 smid;
-       u16 count = 0;
-
-       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
-               scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
-               if (!scmd)
-                       continue;
-               count++;
-               mpt2sas_base_free_smid(ioc, smid);
-               scsi_dma_unmap(scmd);
-               if (ioc->pci_error_recovery)
-                       scmd->result = DID_NO_CONNECT << 16;
-               else
-                       scmd->result = DID_RESET << 16;
-               scmd->scsi_done(scmd);
-       }
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
-           ioc->name, count));
-}
-
-/**
- * _scsih_setup_eedp - setup MPI request for EEDP transfer
- * @scmd: pointer to scsi command object
- * @mpi_request: pointer to the SCSI_IO reqest message frame
- *
- * Supporting protection 1 and 3.
- *
- * Returns nothing
- */
-static void
-_scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request)
-{
-       u16 eedp_flags;
-       unsigned char prot_op = scsi_get_prot_op(scmd);
-       unsigned char prot_type = scsi_get_prot_type(scmd);
-
-       if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
-               return;
-
-       if (prot_op ==  SCSI_PROT_READ_STRIP)
-               eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
-       else if (prot_op ==  SCSI_PROT_WRITE_INSERT)
-               eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
-       else
-               return;
-
-       switch (prot_type) {
-       case SCSI_PROT_DIF_TYPE1:
-       case SCSI_PROT_DIF_TYPE2:
-
-               /*
-               * enable ref/guard checking
-               * auto increment ref tag
-               */
-               eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
-                   MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
-                   MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
-               mpi_request->CDB.EEDP32.PrimaryReferenceTag =
-                   cpu_to_be32(scsi_get_lba(scmd));
-               break;
-
-       case SCSI_PROT_DIF_TYPE3:
-
-               /*
-               * enable guard checking
-               */
-               eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
-               break;
-       }
-       mpi_request->EEDPBlockSize = cpu_to_le32(scmd->device->sector_size);
-       mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
-}
-
-/**
- * _scsih_eedp_error_handling - return sense code for EEDP errors
- * @scmd: pointer to scsi command object
- * @ioc_status: ioc status
- *
- * Returns nothing
- */
-static void
-_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
-{
-       u8 ascq;
-
-       switch (ioc_status) {
-       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
-               ascq = 0x01;
-               break;
-       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
-               ascq = 0x02;
-               break;
-       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
-               ascq = 0x03;
-               break;
-       default:
-               ascq = 0x00;
-               break;
-       }
-
-       scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10, ascq);
-       scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
-           SAM_STAT_CHECK_CONDITION;
-}
-
-/**
- * _scsih_scsi_direct_io_get - returns direct io flag
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static inline u8
-_scsih_scsi_direct_io_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
-{
-       return ioc->scsi_lookup[smid - 1].direct_io;
-}
-
-/**
- * _scsih_scsi_direct_io_set - sets direct io flag
- * @ioc: per adapter object
- * @smid: system request message index
- * @direct_io: Zero or non-zero value to set in the direct_io flag
- *
- * Returns Nothing.
- */
-static inline void
-_scsih_scsi_direct_io_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
-{
-       ioc->scsi_lookup[smid - 1].direct_io = direct_io;
-}
-
-
-/**
- * _scsih_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
- * @ioc: per adapter object
- * @scmd: pointer to scsi command object
- * @raid_device: pointer to raid device data structure
- * @mpi_request: pointer to the SCSI_IO reqest message frame
- * @smid: system request message index
- *
- * Returns nothing
- */
-static void
-_scsih_setup_direct_io(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
-       struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
-       u16 smid)
-{
-       sector_t v_lba, p_lba, stripe_off, column, io_size;
-       u32 stripe_sz, stripe_exp;
-       u8 num_pds, cmd = scmd->cmnd[0];
-
-       if (cmd != READ_10 && cmd != WRITE_10 &&
-           cmd != READ_16 && cmd != WRITE_16)
-               return;
-
-       if (cmd == READ_10 || cmd == WRITE_10)
-               v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]);
-       else
-               v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]);
-
-       io_size = scsi_bufflen(scmd) >> raid_device->block_exponent;
-
-       if (v_lba + io_size - 1 > raid_device->max_lba)
-               return;
-
-       stripe_sz = raid_device->stripe_sz;
-       stripe_exp = raid_device->stripe_exponent;
-       stripe_off = v_lba & (stripe_sz - 1);
-
-       /* Return unless IO falls within a stripe */
-       if (stripe_off + io_size > stripe_sz)
-               return;
-
-       num_pds = raid_device->num_pds;
-       p_lba = v_lba >> stripe_exp;
-       column = sector_div(p_lba, num_pds);
-       p_lba = (p_lba << stripe_exp) + stripe_off;
-
-       mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]);
-
-       if (cmd == READ_10 || cmd == WRITE_10)
-               put_unaligned_be32(lower_32_bits(p_lba),
-                                  &mpi_request->CDB.CDB32[2]);
-       else
-               put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]);
-
-       _scsih_scsi_direct_io_set(ioc, smid, 1);
-}
-
-/**
- * _scsih_qcmd - main scsi request entry point
- * @scmd: pointer to scsi command object
- * @done: function pointer to be invoked on completion
- *
- * The callback index is set inside `ioc->scsi_io_cb_idx`.
- *
- * Returns 0 on success.  If there's a failure, return either:
- * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
- * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
- */
-static int
-_scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct _raid_device *raid_device;
-       Mpi2SCSIIORequest_t *mpi_request;
-       u32 mpi_control;
-       u16 smid;
-
-       sas_device_priv_data = scmd->device->hostdata;
-       if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               return 0;
-       }
-
-       if (ioc->pci_error_recovery || ioc->remove_host) {
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               return 0;
-       }
-
-       sas_target_priv_data = sas_device_priv_data->sas_target;
-       /* invalid device handle */
-       if (sas_target_priv_data->handle == MPT2SAS_INVALID_DEVICE_HANDLE) {
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               return 0;
-       }
-
-       /* host recovery or link resets sent via IOCTLs */
-       if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
-               return SCSI_MLQUEUE_HOST_BUSY;
-       /* device busy with task management */
-       else if (sas_device_priv_data->block || sas_target_priv_data->tm_busy)
-               return SCSI_MLQUEUE_DEVICE_BUSY;
-       /* device has been deleted */
-       else if (sas_target_priv_data->deleted) {
-               scmd->result = DID_NO_CONNECT << 16;
-               scmd->scsi_done(scmd);
-               return 0;
-       }
-
-       if (scmd->sc_data_direction == DMA_FROM_DEVICE)
-               mpi_control = MPI2_SCSIIO_CONTROL_READ;
-       else if (scmd->sc_data_direction == DMA_TO_DEVICE)
-               mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
-       else
-               mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
-
-       /* set tags */
-       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-
-       /* Make sure Device is not raid volume.
-        * We do not expose raid functionality to upper layer for warpdrive.
-        */
-       if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
-           sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
-               mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
-
-       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__);
-               goto out;
-       }
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
-       _scsih_setup_eedp(scmd, mpi_request);
-       if (scmd->cmd_len == 32)
-               mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
-       mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
-       if (sas_device_priv_data->sas_target->flags &
-           MPT_TARGET_FLAGS_RAID_COMPONENT)
-               mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
-       else
-       mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
-       mpi_request->DevHandle =
-           cpu_to_le16(sas_device_priv_data->sas_target->handle);
-       mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
-       mpi_request->Control = cpu_to_le32(mpi_control);
-       mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
-       mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
-       mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
-       mpi_request->SenseBufferLowAddress =
-           mpt2sas_base_get_sense_buffer_dma(ioc, smid);
-       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);
-
-       if (!mpi_request->DataLength) {
-               mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
-       } else {
-               if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
-                       mpt2sas_base_free_smid(ioc, smid);
-                       goto out;
-               }
-       }
-
-       raid_device = sas_target_priv_data->raid_device;
-       if (raid_device && raid_device->direct_io_enabled)
-               _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
-                   smid);
-
-       if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST))
-               mpt2sas_base_put_smid_scsi_io(ioc, smid,
-                   le16_to_cpu(mpi_request->DevHandle));
-       else
-               mpt2sas_base_put_smid_default(ioc, smid);
-       return 0;
-
- out:
-       return SCSI_MLQUEUE_HOST_BUSY;
-}
-
-/**
- * _scsih_normalize_sense - normalize descriptor and fixed format sense data
- * @sense_buffer: sense data returned by target
- * @data: normalized skey/asc/ascq
- *
- * Return nothing.
- */
-static void
-_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
-{
-       if ((sense_buffer[0] & 0x7F) >= 0x72) {
-               /* descriptor format */
-               data->skey = sense_buffer[1] & 0x0F;
-               data->asc = sense_buffer[2];
-               data->ascq = sense_buffer[3];
-       } else {
-               /* fixed format */
-               data->skey = sense_buffer[2] & 0x0F;
-               data->asc = sense_buffer[12];
-               data->ascq = sense_buffer[13];
-       }
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
- * @ioc: per adapter object
- * @scmd: pointer to scsi command object
- * @mpi_reply: reply mf payload returned from firmware
- *
- * scsi_status - SCSI Status code returned from target device
- * scsi_state - state info associated with SCSI_IO determined by ioc
- * ioc_status - ioc supplied status info
- *
- * Return nothing.
- */
-static void
-_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
-    Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
-{
-       u32 response_info;
-       u8 *response_bytes;
-       u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       u8 scsi_state = mpi_reply->SCSIState;
-       u8 scsi_status = mpi_reply->SCSIStatus;
-       char *desc_ioc_state = NULL;
-       char *desc_scsi_status = NULL;
-       char *desc_scsi_state = ioc->tmp_string;
-       u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
-       struct _sas_device *sas_device = NULL;
-       struct scsi_target *starget = scmd->device->sdev_target;
-       struct MPT2SAS_TARGET *priv_target = starget->hostdata;
-       char *device_str = NULL;
-
-       if (!priv_target)
-               return;
-
-       if (ioc->hide_ir_msg)
-               device_str = "WarpDrive";
-       else
-               device_str = "volume";
-
-       if (log_info == 0x31170000)
-               return;
-
-       switch (ioc_status) {
-       case MPI2_IOCSTATUS_SUCCESS:
-               desc_ioc_state = "success";
-               break;
-       case MPI2_IOCSTATUS_INVALID_FUNCTION:
-               desc_ioc_state = "invalid function";
-               break;
-       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
-               desc_ioc_state = "scsi recovered error";
-               break;
-       case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
-               desc_ioc_state = "scsi invalid dev handle";
-               break;
-       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
-               desc_ioc_state = "scsi device not there";
-               break;
-       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
-               desc_ioc_state = "scsi data overrun";
-               break;
-       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
-               desc_ioc_state = "scsi data underrun";
-               break;
-       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
-               desc_ioc_state = "scsi io data error";
-               break;
-       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
-               desc_ioc_state = "scsi protocol error";
-               break;
-       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
-               desc_ioc_state = "scsi task terminated";
-               break;
-       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
-               desc_ioc_state = "scsi residual mismatch";
-               break;
-       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
-               desc_ioc_state = "scsi task mgmt failed";
-               break;
-       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
-               desc_ioc_state = "scsi ioc terminated";
-               break;
-       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
-               desc_ioc_state = "scsi ext terminated";
-               break;
-       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
-               desc_ioc_state = "eedp guard error";
-               break;
-       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
-               desc_ioc_state = "eedp ref tag error";
-               break;
-       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
-               desc_ioc_state = "eedp app tag error";
-               break;
-       default:
-               desc_ioc_state = "unknown";
-               break;
-       }
-
-       switch (scsi_status) {
-       case MPI2_SCSI_STATUS_GOOD:
-               desc_scsi_status = "good";
-               break;
-       case MPI2_SCSI_STATUS_CHECK_CONDITION:
-               desc_scsi_status = "check condition";
-               break;
-       case MPI2_SCSI_STATUS_CONDITION_MET:
-               desc_scsi_status = "condition met";
-               break;
-       case MPI2_SCSI_STATUS_BUSY:
-               desc_scsi_status = "busy";
-               break;
-       case MPI2_SCSI_STATUS_INTERMEDIATE:
-               desc_scsi_status = "intermediate";
-               break;
-       case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
-               desc_scsi_status = "intermediate condmet";
-               break;
-       case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
-               desc_scsi_status = "reservation conflict";
-               break;
-       case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
-               desc_scsi_status = "command terminated";
-               break;
-       case MPI2_SCSI_STATUS_TASK_SET_FULL:
-               desc_scsi_status = "task set full";
-               break;
-       case MPI2_SCSI_STATUS_ACA_ACTIVE:
-               desc_scsi_status = "aca active";
-               break;
-       case MPI2_SCSI_STATUS_TASK_ABORTED:
-               desc_scsi_status = "task aborted";
-               break;
-       default:
-               desc_scsi_status = "unknown";
-               break;
-       }
-
-       desc_scsi_state[0] = '\0';
-       if (!scsi_state)
-               desc_scsi_state = " ";
-       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
-               strcat(desc_scsi_state, "response info ");
-       if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
-               strcat(desc_scsi_state, "state terminated ");
-       if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
-               strcat(desc_scsi_state, "no status ");
-       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
-               strcat(desc_scsi_state, "autosense failed ");
-       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
-               strcat(desc_scsi_state, "autosense valid ");
-
-       scsi_print_command(scmd);
-
-       if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
-               printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
-                   device_str, (unsigned long long)priv_target->sas_address);
-       } else {
-               sas_device = mpt2sas_get_sdev_from_target(ioc, priv_target);
-               if (sas_device) {
-                       printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
-                           "phy(%d)\n", ioc->name, sas_device->sas_address,
-                           sas_device->phy);
-                       printk(MPT2SAS_WARN_FMT
-                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
-                           ioc->name, sas_device->enclosure_logical_id,
-                           sas_device->slot);
-
-                       sas_device_put(sas_device);
-               }
-       }
-
-       printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), "
-           "smid(%d)\n", ioc->name, le16_to_cpu(mpi_reply->DevHandle),
-           desc_ioc_state, ioc_status, smid);
-       printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
-           "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
-           scsi_get_resid(scmd));
-       printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
-           "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
-           le32_to_cpu(mpi_reply->TransferCount), scmd->result);
-       printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
-           "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
-           scsi_status, desc_scsi_state, scsi_state);
-
-       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
-               struct sense_info data;
-               _scsih_normalize_sense(scmd->sense_buffer, &data);
-               printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
-                   "[0x%02x,0x%02x,0x%02x], count(%d)\n", ioc->name, data.skey,
-                   data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
-       }
-
-       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
-               response_info = le32_to_cpu(mpi_reply->ResponseInfo);
-               response_bytes = (u8 *)&response_info;
-               _scsih_response_code(ioc, response_bytes[0]);
-       }
-}
-#endif
-
-/**
- * _scsih_turn_on_pfa_led - illuminate PFA LED
- * @ioc: per adapter object
- * @handle: device handle
- * Context: process
- *
- * Return nothing.
- */
-static void
-_scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       Mpi2SepReply_t mpi_reply;
-       Mpi2SepRequest_t mpi_request;
-       struct _sas_device *sas_device;
-
-       sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (!sas_device)
-               return;
-
-       memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-       mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
-       mpi_request.SlotStatus =
-           cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
-       mpi_request.DevHandle = cpu_to_le16(handle);
-       mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
-       if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
-           &mpi_request)) != 0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
-               __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       sas_device->pfa_led_on = 1;
-
-
-       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
-                ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
-                le32_to_cpu(mpi_reply.IOCLogInfo)));
-               goto out;
-       }
-out:
-       sas_device_put(sas_device);
-}
-
-/**
- * _scsih_turn_off_pfa_led - turn off PFA LED
- * @ioc: per adapter object
- * @sas_device: sas device whose PFA LED has to turned off
- * Context: process
- *
- * Return nothing.
- */
-static void
-_scsih_turn_off_pfa_led(struct MPT2SAS_ADAPTER *ioc,
-       struct _sas_device *sas_device)
-{
-       Mpi2SepReply_t mpi_reply;
-       Mpi2SepRequest_t mpi_request;
-
-       memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
-       mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
-       mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
-       mpi_request.SlotStatus = 0;
-       mpi_request.Slot = cpu_to_le16(sas_device->slot);
-       mpi_request.DevHandle = 0;
-       mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
-       mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
-       if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
-           &mpi_request)) != 0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
-               __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
-                   "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
-                   le16_to_cpu(mpi_reply.IOCStatus),
-                   le32_to_cpu(mpi_reply.IOCLogInfo)));
-               return;
-       }
-}
-
-/**
- * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt.
- *
- * Return nothing.
- */
-static void
-_scsih_send_event_to_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct fw_event_work *fw_event;
-
-       fw_event = alloc_fw_event_work(0);
-       if (!fw_event)
-               return;
-       fw_event->event = MPT2SAS_TURN_ON_PFA_LED;
-       fw_event->device_handle = handle;
-       fw_event->ioc = ioc;
-       _scsih_fw_event_add(ioc, fw_event);
-       fw_event_work_put(fw_event);
-}
-
-/**
- * _scsih_smart_predicted_fault - process smart errors
- * @ioc: per adapter object
- * @handle: device handle
- * Context: interrupt.
- *
- * Return nothing.
- */
-static void
-_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct scsi_target *starget;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       Mpi2EventNotificationReply_t *event_reply;
-       Mpi2EventDataSasDeviceStatusChange_t *event_data;
-       struct _sas_device *sas_device;
-       ssize_t sz;
-       unsigned long flags;
-
-       /* only handle non-raid devices */
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (!sas_device) {
-               goto out_unlock;
-       }
-       starget = sas_device->starget;
-       sas_target_priv_data = starget->hostdata;
-
-       if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
-          ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
-               goto out_unlock;
-
-       starget_printk(KERN_WARNING, starget, "predicted fault\n");
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
-               _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
-
-       /* insert into event log */
-       sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
-            sizeof(Mpi2EventDataSasDeviceStatusChange_t);
-       event_reply = kzalloc(sz, GFP_ATOMIC);
-       if (!event_reply) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-
-       event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
-       event_reply->Event =
-           cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
-       event_reply->MsgLength = sz/4;
-       event_reply->EventDataLength =
-           cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
-       event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
-           event_reply->EventData;
-       event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
-       event_data->ASC = 0x5D;
-       event_data->DevHandle = cpu_to_le16(handle);
-       event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
-       mpt2sas_ctl_add_to_event_log(ioc, event_reply);
-       kfree(event_reply);
-out:
-       if (sas_device)
-               sas_device_put(sas_device);
-       return;
-
-out_unlock:
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       goto out;
-}
-
-/**
- * _scsih_io_done - scsi request callback
- * @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)
- *
- * Callback handler when using _scsih_qcmd.
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-static u8
-_scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
-{
-       Mpi2SCSIIORequest_t *mpi_request;
-       Mpi2SCSIIOReply_t *mpi_reply;
-       struct scsi_cmnd *scmd;
-       u16 ioc_status;
-       u32 xfer_cnt;
-       u8 scsi_state;
-       u8 scsi_status;
-       u32 log_info;
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       u32 response_code = 0;
-       unsigned long flags;
-
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-       scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
-       if (scmd == NULL)
-               return 1;
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-
-       if (mpi_reply == NULL) {
-               scmd->result = DID_OK << 16;
-               goto out;
-       }
-
-       sas_device_priv_data = scmd->device->hostdata;
-       if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
-            sas_device_priv_data->sas_target->deleted) {
-               scmd->result = DID_NO_CONNECT << 16;
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
-       /*
-        * WARPDRIVE: If direct_io is set then it is directIO,
-        * the failed direct I/O should be redirected to volume
-        */
-       if (_scsih_scsi_direct_io_get(ioc, smid) &&
-           ((ioc_status & MPI2_IOCSTATUS_MASK)
-           != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
-               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-               ioc->scsi_lookup[smid - 1].scmd = scmd;
-               _scsih_scsi_direct_io_set(ioc, smid, 0);
-               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-               memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
-               mpi_request->DevHandle =
-                   cpu_to_le16(sas_device_priv_data->sas_target->handle);
-               mpt2sas_base_put_smid_scsi_io(ioc, smid,
-                   sas_device_priv_data->sas_target->handle);
-               return 0;
-       }
-
-
-       /* turning off TLR */
-       scsi_state = mpi_reply->SCSIState;
-       if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
-               response_code =
-                   le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
-       if (!sas_device_priv_data->tlr_snoop_check) {
-               sas_device_priv_data->tlr_snoop_check++;
-       /* Make sure Device is not raid volume.
-        * We do not expose raid functionality to upper layer for warpdrive.
-        */
-       if (!ioc->is_warpdrive && !_scsih_is_raid(&scmd->device->sdev_gendev) &&
-               sas_is_tlr_enabled(scmd->device) &&
-                   response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
-                       sas_disable_tlr(scmd->device);
-                       sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
-               }
-       }
-
-       xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
-       scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
-       if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
-               log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
-       else
-               log_info = 0;
-       ioc_status &= MPI2_IOCSTATUS_MASK;
-       scsi_status = mpi_reply->SCSIStatus;
-
-       if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
-           (scsi_status == MPI2_SCSI_STATUS_BUSY ||
-            scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
-            scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
-               ioc_status = MPI2_IOCSTATUS_SUCCESS;
-       }
-
-       if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
-               struct sense_info data;
-               const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
-                   smid);
-               u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
-                   le32_to_cpu(mpi_reply->SenseCount));
-               memcpy(scmd->sense_buffer, sense_data, sz);
-               _scsih_normalize_sense(scmd->sense_buffer, &data);
-               /* failure prediction threshold exceeded */
-               if (data.asc == 0x5D)
-                       _scsih_smart_predicted_fault(ioc,
-                           le16_to_cpu(mpi_reply->DevHandle));
-       }
-
-       switch (ioc_status) {
-       case MPI2_IOCSTATUS_BUSY:
-       case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
-               scmd->result = SAM_STAT_BUSY;
-               break;
-
-       case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
-               scmd->result = DID_NO_CONNECT << 16;
-               break;
-
-       case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
-               if (sas_device_priv_data->block) {
-                       scmd->result = DID_TRANSPORT_DISRUPTED << 16;
-                       goto out;
-               }
-               if (log_info == 0x32010081) {
-                       scmd->result = DID_RESET << 16;
-                       break;
-               }
-               scmd->result = DID_SOFT_ERROR << 16;
-               break;
-       case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
-       case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
-               scmd->result = DID_RESET << 16;
-               break;
-
-       case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
-               if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
-                       scmd->result = DID_SOFT_ERROR << 16;
-               else
-                       scmd->result = (DID_OK << 16) | scsi_status;
-               break;
-
-       case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
-               scmd->result = (DID_OK << 16) | scsi_status;
-
-               if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
-                       break;
-
-               if (xfer_cnt < scmd->underflow) {
-                       if (scsi_status == SAM_STAT_BUSY)
-                               scmd->result = SAM_STAT_BUSY;
-                       else
-                               scmd->result = DID_SOFT_ERROR << 16;
-               } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
-                    MPI2_SCSI_STATE_NO_SCSI_STATUS))
-                       scmd->result = DID_SOFT_ERROR << 16;
-               else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
-                       scmd->result = DID_RESET << 16;
-               else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
-                       mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
-                       mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
-                       scmd->result = (DRIVER_SENSE << 24) |
-                           SAM_STAT_CHECK_CONDITION;
-                       scmd->sense_buffer[0] = 0x70;
-                       scmd->sense_buffer[2] = ILLEGAL_REQUEST;
-                       scmd->sense_buffer[12] = 0x20;
-                       scmd->sense_buffer[13] = 0;
-               }
-               break;
-
-       case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
-               scsi_set_resid(scmd, 0);
-       case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
-       case MPI2_IOCSTATUS_SUCCESS:
-               scmd->result = (DID_OK << 16) | scsi_status;
-               if (response_code ==
-                   MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
-                   (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
-                    MPI2_SCSI_STATE_NO_SCSI_STATUS)))
-                       scmd->result = DID_SOFT_ERROR << 16;
-               else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
-                       scmd->result = DID_RESET << 16;
-               break;
-
-       case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
-       case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
-       case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
-               _scsih_eedp_error_handling(scmd, ioc_status);
-               break;
-       case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
-       case MPI2_IOCSTATUS_INVALID_FUNCTION:
-       case MPI2_IOCSTATUS_INVALID_SGL:
-       case MPI2_IOCSTATUS_INTERNAL_ERROR:
-       case MPI2_IOCSTATUS_INVALID_FIELD:
-       case MPI2_IOCSTATUS_INVALID_STATE:
-       case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
-       case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
-       default:
-               scmd->result = DID_SOFT_ERROR << 16;
-               break;
-
-       }
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
-               _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
-#endif
-
- out:
-       scsi_dma_unmap(scmd);
-       scmd->scsi_done(scmd);
-       return 1;
-}
-
-/**
- * _scsih_sas_host_refresh - refreshing sas host object contents
- * @ioc: per adapter object
- * Context: user
- *
- * During port enable, fw will send topology events for every device. Its
- * possible that the handles may change from the previous setting, so this
- * code keeping handles updating if changed.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc)
-{
-       u16 sz;
-       u16 ioc_status;
-       int i;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
-       u16 attached_handle;
-       u8 link_rate;
-
-       dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
-           "updating handles for sas_host(0x%016llx)\n",
-           ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
-
-       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
-           * sizeof(Mpi2SasIOUnit0PhyData_t));
-       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
-           sas_iounit_pg0, sz)) != 0)
-               goto out;
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-               goto out;
-       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
-               link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
-               if (i == 0)
-                       ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
-                           PhyData[0].ControllerDevHandle);
-               ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
-               attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
-                   AttachedDevHandle);
-               if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
-                       link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
-               mpt2sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
-                   attached_handle, i, link_rate);
-       }
- out:
-       kfree(sas_iounit_pg0);
-}
-
-/**
- * _scsih_sas_host_add - create sas host object
- * @ioc: per adapter object
- *
- * Creating host side data object, stored in ioc->sas_hba
- *
- * Return nothing.
- */
-static void
-_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
-{
-       int i;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
-       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
-       Mpi2SasPhyPage0_t phy_pg0;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2SasEnclosurePage0_t enclosure_pg0;
-       u16 ioc_status;
-       u16 sz;
-       u16 device_missing_delay;
-
-       mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
-       if (!ioc->sas_hba.num_phys) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       /* sas_iounit page 0 */
-       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
-           sizeof(Mpi2SasIOUnit0PhyData_t));
-       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
-           sas_iounit_pg0, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-
-       /* sas_iounit page 1 */
-       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
-           sizeof(Mpi2SasIOUnit1PhyData_t));
-       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg1) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
-           sas_iounit_pg1, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-
-       ioc->io_missing_delay =
-           le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
-       device_missing_delay =
-           le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
-       if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
-               ioc->device_missing_delay = (device_missing_delay &
-                   MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
-       else
-               ioc->device_missing_delay = device_missing_delay &
-                   MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
-
-       ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
-       ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
-           sizeof(struct _sas_phy), GFP_KERNEL);
-       if (!ioc->sas_hba.phy) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
-               if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
-                   i))) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       goto out;
-               }
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       goto out;
-               }
-
-               if (i == 0)
-                       ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
-                           PhyData[0].ControllerDevHandle);
-               ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
-               ioc->sas_hba.phy[i].phy_id = i;
-               mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
-                   phy_pg0, ioc->sas_hba.parent_dev);
-       }
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out;
-       }
-       ioc->sas_hba.enclosure_handle =
-           le16_to_cpu(sas_device_pg0.EnclosureHandle);
-       ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-       printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
-           "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
-           (unsigned long long) ioc->sas_hba.sas_address,
-           ioc->sas_hba.num_phys) ;
-
-       if (ioc->sas_hba.enclosure_handle) {
-               if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
-                   &enclosure_pg0,
-                  MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
-                  ioc->sas_hba.enclosure_handle))) {
-                       ioc->sas_hba.enclosure_logical_id =
-                           le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-               }
-       }
-
- out:
-       kfree(sas_iounit_pg1);
-       kfree(sas_iounit_pg0);
-}
-
-/**
- * _scsih_expander_add -  creating expander object
- * @ioc: per adapter object
- * @handle: expander handle
- *
- * Creating expander object, stored in ioc->sas_expander_list.
- *
- * Return 0 for success, else error.
- */
-static int
-_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_node *sas_expander;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2ExpanderPage0_t expander_pg0;
-       Mpi2ExpanderPage1_t expander_pg1;
-       Mpi2SasEnclosurePage0_t enclosure_pg0;
-       u32 ioc_status;
-       u16 parent_handle;
-       u64 sas_address, sas_address_parent = 0;
-       int i;
-       unsigned long flags;
-       struct _sas_port *mpt2sas_port = NULL;
-       int rc = 0;
-
-       if (!handle)
-               return -1;
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery)
-               return -1;
-
-       if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
-           MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       /* handle out of order topology events */
-       parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
-       if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
-           != 0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-       if (sas_address_parent != ioc->sas_hba.sas_address) {
-               spin_lock_irqsave(&ioc->sas_node_lock, flags);
-               sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
-                   sas_address_parent);
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               if (!sas_expander) {
-                       rc = _scsih_expander_add(ioc, parent_handle);
-                       if (rc != 0)
-                               return rc;
-               }
-       }
-
-       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);
-
-       if (sas_expander)
-               return 0;
-
-       sas_expander = kzalloc(sizeof(struct _sas_node),
-           GFP_KERNEL);
-       if (!sas_expander) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       sas_expander->handle = handle;
-       sas_expander->num_phys = expander_pg0.NumPhys;
-       sas_expander->sas_address_parent = sas_address_parent;
-       sas_expander->sas_address = sas_address;
-
-       printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
-           " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
-           handle, parent_handle, (unsigned long long)
-           sas_expander->sas_address, sas_expander->num_phys);
-
-       if (!sas_expander->num_phys)
-               goto out_fail;
-       sas_expander->phy = kcalloc(sas_expander->num_phys,
-           sizeof(struct _sas_phy), GFP_KERNEL);
-       if (!sas_expander->phy) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -1;
-               goto out_fail;
-       }
-
-       INIT_LIST_HEAD(&sas_expander->sas_port_list);
-       mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
-           sas_address_parent);
-       if (!mpt2sas_port) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -1;
-               goto out_fail;
-       }
-       sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
-
-       for (i = 0 ; i < sas_expander->num_phys ; i++) {
-               if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
-                   &expander_pg1, i, handle))) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       rc = -1;
-                       goto out_fail;
-               }
-               sas_expander->phy[i].handle = handle;
-               sas_expander->phy[i].phy_id = i;
-
-               if ((mpt2sas_transport_add_expander_phy(ioc,
-                   &sas_expander->phy[i], expander_pg1,
-                   sas_expander->parent_dev))) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       rc = -1;
-                       goto out_fail;
-               }
-       }
-
-       if (sas_expander->enclosure_handle) {
-               if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
-                   &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
-                  sas_expander->enclosure_handle))) {
-                       sas_expander->enclosure_logical_id =
-                           le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-               }
-       }
-
-       _scsih_expander_node_add(ioc, sas_expander);
-        return 0;
-
- out_fail:
-
-       if (mpt2sas_port)
-               mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
-                   sas_address_parent);
-       kfree(sas_expander);
-       return rc;
-}
-
-/**
- * _scsih_done -  scsih callback handler.
- * @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)
- *
- * Callback handler when sending internal generated message frames.
- * The callback index passed is `ioc->scsih_cb_idx`
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-static u8
-_scsih_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->scsih_cmds.status == MPT2_CMD_NOT_USED)
-               return 1;
-       if (ioc->scsih_cmds.smid != smid)
-               return 1;
-       ioc->scsih_cmds.status |= MPT2_CMD_COMPLETE;
-       if (mpi_reply) {
-               memcpy(ioc->scsih_cmds.reply, mpi_reply,
-                   mpi_reply->MsgLength*4);
-               ioc->scsih_cmds.status |= MPT2_CMD_REPLY_VALID;
-       }
-       ioc->scsih_cmds.status &= ~MPT2_CMD_PENDING;
-       complete(&ioc->scsih_cmds.done);
-       return 1;
-}
-
-/**
- * mpt2sas_expander_remove - removing expander object
- * @ioc: per adapter object
- * @sas_address: expander sas_address
- *
- * Return nothing.
- */
-void
-mpt2sas_expander_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
-{
-       struct _sas_node *sas_expander;
-       unsigned long flags;
-
-       if (ioc->shost_recovery)
-               return;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
-           sas_address);
-       if (sas_expander)
-               list_del(&sas_expander->list);
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-       if (sas_expander)
-               _scsih_expander_node_remove(ioc, sas_expander);
-}
-
-/**
- * _scsih_check_access_status - check access flags
- * @ioc: per adapter object
- * @sas_address: sas address
- * @handle: sas device handle
- * @access_flags: errors returned during discovery of the device
- *
- * Return 0 for success, else failure
- */
-static u8
-_scsih_check_access_status(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
-   u16 handle, u8 access_status)
-{
-       u8 rc = 1;
-       char *desc = NULL;
-
-       switch (access_status) {
-       case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
-       case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
-               rc = 0;
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
-               desc = "sata capability failed";
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
-               desc = "sata affiliation conflict";
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
-               desc = "route not addressable";
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
-               desc = "smp error not addressable";
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
-               desc = "device blocked";
-               break;
-       case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
-       case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
-               desc = "sata initialization failed";
-               break;
-       default:
-               desc = "unknown";
-               break;
-       }
-
-       if (!rc)
-               return 0;
-
-       printk(MPT2SAS_ERR_FMT "discovery errors(%s): sas_address(0x%016llx), "
-           "handle(0x%04x)\n", ioc->name, desc,
-           (unsigned long long)sas_address, handle);
-       return rc;
-}
-
-static void
-_scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       struct _sas_device *sas_device;
-       u32 ioc_status;
-       unsigned long flags;
-       u64 sas_address;
-       struct scsi_target *starget;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       u32 device_info;
-
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
-               return;
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-               return;
-
-       /* check if this is end device */
-       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-       if (!(_scsih_is_end_device(device_info)))
-               return;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-           sas_address);
-
-       if (!sas_device) {
-               printk(MPT2SAS_ERR_FMT "device is not present "
-                   "handle(0x%04x), no sas_device!!!\n", ioc->name, handle);
-               goto out_unlock;
-       }
-
-       if (unlikely(sas_device->handle != handle)) {
-               starget = sas_device->starget;
-               sas_target_priv_data = starget->hostdata;
-               starget_printk(KERN_INFO, starget, "handle changed from(0x%04x)"
-                  " to (0x%04x)!!!\n", sas_device->handle, handle);
-               sas_target_priv_data->handle = handle;
-               sas_device->handle = handle;
-       }
-
-       /* check if device is present */
-       if (!(le16_to_cpu(sas_device_pg0.Flags) &
-           MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
-               printk(MPT2SAS_ERR_FMT "device is not present "
-                   "handle(0x%04x), flags!!!\n", ioc->name, handle);
-               goto out_unlock;
-       }
-
-       /* check if there were any issues with discovery */
-       if (_scsih_check_access_status(ioc, sas_address, handle,
-           sas_device_pg0.AccessStatus))
-               goto out_unlock;
-
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       _scsih_ublock_io_device(ioc, sas_address);
-       if (sas_device)
-               sas_device_put(sas_device);
-       return;
-
-out_unlock:
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (sas_device)
-               sas_device_put(sas_device);
-}
-
-/**
- * _scsih_add_device -  creating sas device object
- * @ioc: per adapter object
- * @handle: sas device handle
- * @phy_num: phy number end device attached to
- * @is_pd: is this hidden raid component
- *
- * Creating end device object, stored in ioc->sas_device_list.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
-{
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2SasEnclosurePage0_t enclosure_pg0;
-       struct _sas_device *sas_device;
-       u32 ioc_status;
-       __le64 sas_address;
-       u32 device_info;
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-
-       /* check if device is present */
-       if (!(le16_to_cpu(sas_device_pg0.Flags) &
-           MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
-                   ioc->name, le16_to_cpu(sas_device_pg0.Flags));
-               return -1;
-       }
-
-       /* check if there were any issues with discovery */
-       if (_scsih_check_access_status(ioc, sas_address, handle,
-           sas_device_pg0.AccessStatus))
-               return -1;
-
-       /* check if this is end device */
-       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-       if (!(_scsih_is_end_device(device_info))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       sas_device = mpt2sas_get_sdev_by_addr(ioc,
-           sas_address);
-
-       if (sas_device) {
-               sas_device_put(sas_device);
-               return 0;
-       }
-
-       sas_device = kzalloc(sizeof(struct _sas_device),
-           GFP_KERNEL);
-       if (!sas_device) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-
-       kref_init(&sas_device->refcount);
-       sas_device->handle = handle;
-       if (_scsih_get_sas_address(ioc, le16_to_cpu
-               (sas_device_pg0.ParentDevHandle),
-               &sas_device->sas_address_parent) != 0)
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-       sas_device->enclosure_handle =
-           le16_to_cpu(sas_device_pg0.EnclosureHandle);
-       sas_device->slot =
-           le16_to_cpu(sas_device_pg0.Slot);
-       sas_device->device_info = device_info;
-       sas_device->sas_address = sas_address;
-       sas_device->phy = sas_device_pg0.PhyNum;
-
-       /* get enclosure_logical_id */
-       if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
-          ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
-          sas_device->enclosure_handle)))
-               sas_device->enclosure_logical_id =
-                   le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
-       /* get device name */
-       sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
-
-       if (ioc->wait_for_discovery_to_complete)
-               _scsih_sas_device_init_add(ioc, sas_device);
-       else
-               _scsih_sas_device_add(ioc, sas_device);
-
-       sas_device_put(sas_device);
-       return 0;
-}
-
-/**
- * _scsih_remove_device -  removing sas device object
- * @ioc: per adapter object
- * @sas_device_delete: the sas_device object
- *
- * Return nothing.
- */
-static void
-_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_device *sas_device)
-{
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-
-       if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
-               (sas_device->pfa_led_on)) {
-               _scsih_turn_off_pfa_led(ioc, sas_device);
-               sas_device->pfa_led_on = 0;
-       }
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: "
-           "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
-               sas_device->handle, (unsigned long long)
-           sas_device->sas_address));
-
-       if (sas_device->starget && sas_device->starget->hostdata) {
-               sas_target_priv_data = sas_device->starget->hostdata;
-               sas_target_priv_data->deleted = 1;
-               _scsih_ublock_io_device(ioc, sas_device->sas_address);
-               sas_target_priv_data->handle =
-                    MPT2SAS_INVALID_DEVICE_HANDLE;
-       }
-
-       if (!ioc->hide_drives)
-               mpt2sas_transport_port_remove(ioc,
-                   sas_device->sas_address,
-                   sas_device->sas_address_parent);
-
-       printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
-           "(0x%016llx)\n", ioc->name, sas_device->handle,
-           (unsigned long long) sas_device->sas_address);
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: "
-           "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
-           sas_device->handle, (unsigned long long)
-           sas_device->sas_address));
-}
-/**
- * _scsih_device_remove_by_handle - removing device object by handle
- * @ioc: per adapter object
- * @handle: device handle
- *
- * Return nothing.
- */
-static void
-_scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       if (ioc->shost_recovery)
-               return;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (sas_device) {
-               list_del_init(&sas_device->list);
-               sas_device_put(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (sas_device) {
-               _scsih_remove_device(ioc, sas_device);
-               sas_device_put(sas_device);
-       }
-}
-
-/**
- * mpt2sas_device_remove_by_sas_address - removing device object by sas address
- * @ioc: per adapter object
- * @sas_address: device sas_address
- *
- * Return nothing.
- */
-void
-mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
-       u64 sas_address)
-{
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       if (ioc->shost_recovery)
-               return;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc, sas_address);
-       if (sas_device) {
-               list_del_init(&sas_device->list);
-               sas_device_put(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (sas_device) {
-               _scsih_remove_device(ioc, sas_device);
-               sas_device_put(sas_device);
-       }
-}
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_topology_change_event_debug - debug for topology event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- */
-static void
-_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataSasTopologyChangeList_t *event_data)
-{
-       int i;
-       u16 handle;
-       u16 reason_code;
-       u8 phy_number;
-       char *status_str = NULL;
-       u8 link_rate, prev_link_rate;
-
-       switch (event_data->ExpStatus) {
-       case MPI2_EVENT_SAS_TOPO_ES_ADDED:
-               status_str = "add";
-               break;
-       case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
-               status_str = "remove";
-               break;
-       case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
-       case 0:
-               status_str =  "responding";
-               break;
-       case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
-               status_str = "remove delay";
-               break;
-       default:
-               status_str = "unknown status";
-               break;
-       }
-       printk(MPT2SAS_INFO_FMT "sas topology change: (%s)\n",
-           ioc->name, status_str);
-       printk(KERN_INFO "\thandle(0x%04x), enclosure_handle(0x%04x) "
-           "start_phy(%02d), count(%d)\n",
-           le16_to_cpu(event_data->ExpanderDevHandle),
-           le16_to_cpu(event_data->EnclosureHandle),
-           event_data->StartPhyNum, event_data->NumEntries);
-       for (i = 0; i < event_data->NumEntries; i++) {
-               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;
-               switch (reason_code) {
-               case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
-                       status_str = "target add";
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
-                       status_str = "target remove";
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
-                       status_str = "delay target remove";
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
-                       status_str = "link rate change";
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
-                       status_str = "target responding";
-                       break;
-               default:
-                       status_str = "unknown";
-                       break;
-               }
-               link_rate = event_data->PHY[i].LinkRate >> 4;
-               prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
-               printk(KERN_INFO "\tphy(%02d), attached_handle(0x%04x): %s:"
-                   " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
-                   handle, status_str, link_rate, prev_link_rate);
-
-       }
-}
-#endif
-
-/**
- * _scsih_sas_topology_change_event - handle topology changes
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- */
-static void
-_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       int i;
-       u16 parent_handle, handle;
-       u16 reason_code;
-       u8 phy_number, max_phys;
-       struct _sas_node *sas_expander;
-       u64 sas_address;
-       unsigned long flags;
-       u8 link_rate, prev_link_rate;
-       Mpi2EventDataSasTopologyChangeList_t *event_data =
-               (Mpi2EventDataSasTopologyChangeList_t *)
-               fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-               _scsih_sas_topology_change_event_debug(ioc, event_data);
-#endif
-
-       if (ioc->remove_host || ioc->pci_error_recovery)
-               return;
-
-       if (!ioc->sas_hba.num_phys)
-               _scsih_sas_host_add(ioc);
-       else
-               _scsih_sas_host_refresh(ioc);
-
-       if (fw_event->ignore) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring expander "
-                   "event\n", ioc->name));
-               return;
-       }
-
-       parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
-
-       /* handle expander add */
-       if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
-               if (_scsih_expander_add(ioc, parent_handle) != 0)
-                       return;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
-           parent_handle);
-       if (sas_expander) {
-               sas_address = sas_expander->sas_address;
-               max_phys = sas_expander->num_phys;
-       } else if (parent_handle < ioc->sas_hba.num_phys) {
-               sas_address = ioc->sas_hba.sas_address;
-               max_phys = ioc->sas_hba.num_phys;
-       } else {
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       /* handle siblings events */
-       for (i = 0; i < event_data->NumEntries; i++) {
-               if (fw_event->ignore) {
-                       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "ignoring "
-                           "expander event\n", ioc->name));
-                       return;
-               }
-               if (ioc->shost_recovery || ioc->remove_host ||
-                   ioc->pci_error_recovery)
-                       return;
-               phy_number = event_data->StartPhyNum + i;
-               if (phy_number >= max_phys)
-                       continue;
-               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;
-               link_rate = event_data->PHY[i].LinkRate >> 4;
-               prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
-               switch (reason_code) {
-               case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
-
-                       if (ioc->shost_recovery)
-                               break;
-
-                       if (link_rate == prev_link_rate)
-                               break;
-
-                       mpt2sas_transport_update_links(ioc, sas_address,
-                           handle, phy_number, link_rate);
-
-                       if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
-                               break;
-
-                       _scsih_check_device(ioc, handle);
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
-
-                       if (ioc->shost_recovery)
-                               break;
-
-                       mpt2sas_transport_update_links(ioc, sas_address,
-                           handle, phy_number, link_rate);
-
-                       _scsih_add_device(ioc, handle, phy_number, 0);
-                       break;
-               case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
-
-                       _scsih_device_remove_by_handle(ioc, handle);
-                       break;
-               }
-       }
-
-       /* handle expander removal */
-       if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
-           sas_expander)
-               mpt2sas_expander_remove(ioc, sas_address);
-
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_device_status_change_event_debug - debug for device event
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataSasDeviceStatusChange_t *event_data)
-{
-       char *reason_str = NULL;
-
-       switch (event_data->ReasonCode) {
-       case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
-               reason_str = "smart data";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
-               reason_str = "unsupported device discovered";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
-               reason_str = "internal device reset";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
-               reason_str = "internal task abort";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
-               reason_str = "internal task abort set";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
-               reason_str = "internal clear task set";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
-               reason_str = "internal query task";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
-               reason_str = "sata init failure";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
-               reason_str = "internal device reset complete";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
-               reason_str = "internal task abort complete";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
-               reason_str = "internal async notification";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
-               reason_str = "expander reduced functionality";
-               break;
-       case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
-               reason_str = "expander reduced functionality complete";
-               break;
-       default:
-               reason_str = "unknown reason";
-               break;
-       }
-       printk(MPT2SAS_INFO_FMT "device status change: (%s)\n"
-           "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
-           ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
-           (unsigned long long)le64_to_cpu(event_data->SASAddress),
-           le16_to_cpu(event_data->TaskTag));
-       if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
-               printk(MPT2SAS_INFO_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
-                   event_data->ASC, event_data->ASCQ);
-       printk(KERN_INFO "\n");
-}
-#endif
-
-/**
- * _scsih_sas_device_status_change_event - handle device status change
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       struct MPT2SAS_TARGET *target_priv_data;
-       struct _sas_device *sas_device;
-       u64 sas_address;
-       unsigned long flags;
-       Mpi2EventDataSasDeviceStatusChange_t *event_data =
-               (Mpi2EventDataSasDeviceStatusChange_t *)
-               fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-               _scsih_sas_device_status_change_event_debug(ioc,
-                    event_data);
-#endif
-
-       /* In MPI Revision K (0xC), the internal device reset complete was
-        * implemented, so avoid setting tm_busy flag for older firmware.
-        */
-       if ((ioc->facts.HeaderVersion >> 8) < 0xC)
-               return;
-
-       if (event_data->ReasonCode !=
-           MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
-          event_data->ReasonCode !=
-           MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
-               return;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_address = le64_to_cpu(event_data->SASAddress);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-           sas_address);
-
-       if (!sas_device || !sas_device->starget)
-               goto out;
-
-       target_priv_data = sas_device->starget->hostdata;
-       if (!target_priv_data)
-               goto out;
-
-       if (event_data->ReasonCode ==
-           MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
-               target_priv_data->tm_busy = 1;
-       else
-               target_priv_data->tm_busy = 0;
-
-out:
-       if (sas_device)
-               sas_device_put(sas_device);
-
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataSasEnclDevStatusChange_t *event_data)
-{
-       char *reason_str = NULL;
-
-       switch (event_data->ReasonCode) {
-       case MPI2_EVENT_SAS_ENCL_RC_ADDED:
-               reason_str = "enclosure add";
-               break;
-       case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
-               reason_str = "enclosure remove";
-               break;
-       default:
-               reason_str = "unknown reason";
-               break;
-       }
-
-       printk(MPT2SAS_INFO_FMT "enclosure status change: (%s)\n"
-           "\thandle(0x%04x), enclosure logical id(0x%016llx)"
-           " number slots(%d)\n", ioc->name, reason_str,
-           le16_to_cpu(event_data->EnclosureHandle),
-           (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
-           le16_to_cpu(event_data->StartSlot));
-}
-#endif
-
-/**
- * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_enclosure_dev_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_enclosure_dev_status_change_event_debug(ioc,
-                    (Mpi2EventDataSasEnclDevStatusChange_t *)
-                    fw_event->event_data);
-#endif
-}
-
-/**
- * _scsih_sas_broadcast_primitive_event - handle broadcast events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       struct scsi_cmnd *scmd;
-       struct scsi_device *sdev;
-       u16 smid, handle;
-       u32 lun;
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       u32 termination_count;
-       u32 query_count;
-       Mpi2SCSITaskManagementReply_t *mpi_reply;
-       Mpi2EventDataSasBroadcastPrimitive_t *event_data =
-               (Mpi2EventDataSasBroadcastPrimitive_t *)
-               fw_event->event_data;
-       u16 ioc_status;
-       unsigned long flags;
-       int r;
-       u8 max_retries = 0;
-       u8 task_abort_retries;
-
-       mutex_lock(&ioc->tm_cmds.mutex);
-       pr_info(MPT2SAS_FMT
-               "%s: enter: phy number(%d), width(%d)\n",
-               ioc->name, __func__, event_data->PhyNum,
-               event_data->PortWidth);
-
-       _scsih_block_io_all_device(ioc);
-
-       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       mpi_reply = ioc->tm_cmds.reply;
-broadcast_aen_retry:
-
-       /* sanity checks for retrying this loop */
-       if (max_retries++ == 5) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: giving up\n",
-                   ioc->name, __func__));
-               goto out;
-       } else if (max_retries > 1)
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: %d retry\n",
-                   ioc->name, __func__, max_retries - 1));
-
-       termination_count = 0;
-       query_count = 0;
-       for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
-               if (ioc->shost_recovery)
-                       goto out;
-               scmd = _scsih_scsi_lookup_get(ioc, smid);
-               if (!scmd)
-                       continue;
-               sdev = scmd->device;
-               sas_device_priv_data = sdev->hostdata;
-               if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
-                       continue;
-                /* skip hidden raid components */
-               if (sas_device_priv_data->sas_target->flags &
-                   MPT_TARGET_FLAGS_RAID_COMPONENT)
-                       continue;
-                /* skip volumes */
-               if (sas_device_priv_data->sas_target->flags &
-                   MPT_TARGET_FLAGS_VOLUME)
-                       continue;
-
-               handle = sas_device_priv_data->sas_target->handle;
-               lun = sas_device_priv_data->lun;
-               query_count++;
-
-               if (ioc->shost_recovery)
-                       goto out;
-
-               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-               r = mpt2sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
-                   MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30,
-                   TM_MUTEX_OFF);
-               if (r == FAILED) {
-                       sdev_printk(KERN_WARNING, sdev,
-                           "mpt2sas_scsih_issue_tm: FAILED when sending "
-                           "QUERY_TASK: scmd(%p)\n", scmd);
-                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-                       goto broadcast_aen_retry;
-               }
-               ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
-                   & MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       sdev_printk(KERN_WARNING, sdev, "query task: FAILED "
-                           "with IOCSTATUS(0x%04x), scmd(%p)\n", ioc_status,
-                           scmd);
-                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-                       goto broadcast_aen_retry;
-               }
-
-               /* see if IO is still owned by IOC and target */
-               if (mpi_reply->ResponseCode ==
-                    MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
-                    mpi_reply->ResponseCode ==
-                    MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
-                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-                       continue;
-               }
-               task_abort_retries = 0;
- tm_retry:
-               if (task_abort_retries++ == 60) {
-                       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                           "%s: ABORT_TASK: giving up\n", ioc->name,
-                           __func__));
-                       spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-                       goto broadcast_aen_retry;
-               }
-
-               if (ioc->shost_recovery)
-                       goto out_no_lock;
-
-               r = mpt2sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
-                   sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
-                   TM_MUTEX_OFF);
-               if (r == FAILED) {
-                       sdev_printk(KERN_WARNING, sdev,
-                           "mpt2sas_scsih_issue_tm: ABORT_TASK: FAILED : "
-                           "scmd(%p)\n", scmd);
-                       goto tm_retry;
-               }
-
-               if (task_abort_retries > 1)
-                       sdev_printk(KERN_WARNING, sdev,
-                           "mpt2sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
-                           " scmd(%p)\n",
-                           task_abort_retries - 1, scmd);
-
-               termination_count += le32_to_cpu(mpi_reply->TerminationCount);
-               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-       }
-
-       if (ioc->broadcast_aen_pending) {
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: loop back due to"
-                    " pending AEN\n", ioc->name, __func__));
-                ioc->broadcast_aen_pending = 0;
-                goto broadcast_aen_retry;
-       }
-
- out:
-       spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- out_no_lock:
-
-       dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-           "%s - exit, query_count = %d termination_count = %d\n",
-           ioc->name, __func__, query_count, termination_count));
-
-       ioc->broadcast_aen_busy = 0;
-       if (!ioc->shost_recovery)
-               _scsih_ublock_io_all_device(ioc);
-       mutex_unlock(&ioc->tm_cmds.mutex);
-}
-
-/**
- * _scsih_sas_discovery_event - handle discovery events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       Mpi2EventDataSasDiscovery_t *event_data =
-               (Mpi2EventDataSasDiscovery_t *)
-               fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
-               printk(MPT2SAS_INFO_FMT "discovery event: (%s)", ioc->name,
-                   (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
-                   "start" : "stop");
-       if (event_data->DiscoveryStatus)
-               printk("discovery_status(0x%08x)",
-                   le32_to_cpu(event_data->DiscoveryStatus));
-       printk("\n");
-       }
-#endif
-
-       if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
-           !ioc->sas_hba.num_phys) {
-               if (disable_discovery > 0 && ioc->shost_recovery) {
-                       /* Wait for the reset to complete */
-                       while (ioc->shost_recovery)
-                               ssleep(1);
-               }
-               _scsih_sas_host_add(ioc);
-       }
-}
-
-/**
- * _scsih_reprobe_lun - reprobing lun
- * @sdev: scsi device struct
- * @no_uld_attach: sdev->no_uld_attach flag setting
- *
- **/
-static void
-_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
-{
-       int rc;
-
-       sdev->no_uld_attach = no_uld_attach ? 1 : 0;
-       sdev_printk(KERN_INFO, sdev, "%s raid component\n",
-           sdev->no_uld_attach ? "hidding" : "exposing");
-       rc = scsi_device_reprobe(sdev);
-}
-
-/**
- * _scsih_sas_volume_add - add new volume
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventIrConfigElement_t *element)
-{
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       u64 wwid;
-       u16 handle = le16_to_cpu(element->VolDevHandle);
-       int rc;
-
-       mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
-       if (!wwid) {
-               printk(MPT2SAS_ERR_FMT
-                   "failure at %s:%d/%s()!\n", ioc->name,
-                   __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
-       if (raid_device)
-               return;
-
-       raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
-       if (!raid_device) {
-               printk(MPT2SAS_ERR_FMT
-                   "failure at %s:%d/%s()!\n", ioc->name,
-                   __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       raid_device->id = ioc->sas_id++;
-       raid_device->channel = RAID_CHANNEL;
-       raid_device->handle = handle;
-       raid_device->wwid = wwid;
-       _scsih_raid_device_add(ioc, raid_device);
-       if (!ioc->wait_for_discovery_to_complete) {
-               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
-                   raid_device->id, 0);
-               if (rc)
-                       _scsih_raid_device_remove(ioc, raid_device);
-       } else {
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               _scsih_determine_boot_device(ioc, raid_device, 1);
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       }
-}
-
-/**
- * _scsih_sas_volume_delete - delete volume
- * @ioc: per adapter object
- * @handle: volume device handle
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc, u16 handle)
-{
-       struct _raid_device *raid_device;
-       unsigned long flags;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct scsi_target *starget = NULL;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-       if (raid_device) {
-               if (raid_device->starget) {
-                       starget = raid_device->starget;
-                       sas_target_priv_data = starget->hostdata;
-                       sas_target_priv_data->deleted = 1;
-               }
-               printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
-                   "(0x%016llx)\n", ioc->name,  raid_device->handle,
-                   (unsigned long long) raid_device->wwid);
-               list_del(&raid_device->list);
-               kfree(raid_device);
-       }
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       if (starget)
-               scsi_remove_target(&starget->dev);
-}
-
-/**
- * _scsih_sas_pd_expose - expose pd component to /dev/sdX
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventIrConfigElement_t *element)
-{
-       struct _sas_device *sas_device;
-       struct scsi_target *starget = NULL;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       unsigned long flags;
-       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (sas_device) {
-               sas_device->volume_handle = 0;
-               sas_device->volume_wwid = 0;
-               clear_bit(handle, ioc->pd_handles);
-               if (sas_device->starget && sas_device->starget->hostdata) {
-                       starget = sas_device->starget;
-                       sas_target_priv_data = starget->hostdata;
-                       sas_target_priv_data->flags &=
-                           ~MPT_TARGET_FLAGS_RAID_COMPONENT;
-               }
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (!sas_device)
-               return;
-
-       /* exposing raid component */
-       if (starget)
-               starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
-
-       sas_device_put(sas_device);
-}
-
-/**
- * _scsih_sas_pd_hide - hide pd component from /dev/sdX
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventIrConfigElement_t *element)
-{
-       struct _sas_device *sas_device;
-       struct scsi_target *starget = NULL;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       unsigned long flags;
-       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-       u16 volume_handle = 0;
-       u64 volume_wwid = 0;
-
-       mpt2sas_config_get_volume_handle(ioc, handle, &volume_handle);
-       if (volume_handle)
-               mpt2sas_config_get_volume_wwid(ioc, volume_handle,
-                   &volume_wwid);
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (sas_device) {
-               set_bit(handle, ioc->pd_handles);
-               if (sas_device->starget && sas_device->starget->hostdata) {
-                       starget = sas_device->starget;
-                       sas_target_priv_data = starget->hostdata;
-                       sas_target_priv_data->flags |=
-                           MPT_TARGET_FLAGS_RAID_COMPONENT;
-                       sas_device->volume_handle = volume_handle;
-                       sas_device->volume_wwid = volume_wwid;
-               }
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (!sas_device)
-               return;
-
-       /* hiding raid component */
-       if (starget)
-               starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
-
-       sas_device_put(sas_device);
-}
-
-/**
- * _scsih_sas_pd_delete - delete pd component
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventIrConfigElement_t *element)
-{
-       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-
-       _scsih_device_remove_by_handle(ioc, handle);
-}
-
-/**
- * _scsih_sas_pd_add - remove pd component
- * @ioc: per adapter object
- * @element: IR config element data
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventIrConfigElement_t *element)
-{
-       struct _sas_device *sas_device;
-       u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       u32 ioc_status;
-       u64 sas_address;
-       u16 parent_handle;
-
-       set_bit(handle, ioc->pd_handles);
-
-       sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
-       if (sas_device) {
-               sas_device_put(sas_device);
-               return;
-       }
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
-       if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
-               mpt2sas_transport_update_links(ioc, sas_address, handle,
-                   sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
-
-       _scsih_add_device(ioc, handle, 0, 1);
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataIrConfigChangeList_t *event_data)
-{
-       Mpi2EventIrConfigElement_t *element;
-       u8 element_type;
-       int i;
-       char *reason_str = NULL, *element_str = NULL;
-
-       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-
-       printk(MPT2SAS_INFO_FMT "raid config change: (%s), elements(%d)\n",
-           ioc->name, (le32_to_cpu(event_data->Flags) &
-           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
-           "foreign" : "native", event_data->NumElements);
-       for (i = 0; i < event_data->NumElements; i++, element++) {
-               switch (element->ReasonCode) {
-               case MPI2_EVENT_IR_CHANGE_RC_ADDED:
-                       reason_str = "add";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
-                       reason_str = "remove";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
-                       reason_str = "no change";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_HIDE:
-                       reason_str = "hide";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
-                       reason_str = "unhide";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
-                       reason_str = "volume_created";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
-                       reason_str = "volume_deleted";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
-                       reason_str = "pd_created";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
-                       reason_str = "pd_deleted";
-                       break;
-               default:
-                       reason_str = "unknown reason";
-                       break;
-               }
-               element_type = le16_to_cpu(element->ElementFlags) &
-                   MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
-               switch (element_type) {
-               case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
-                       element_str = "volume";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
-                       element_str = "phys disk";
-                       break;
-               case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
-                       element_str = "hot spare";
-                       break;
-               default:
-                       element_str = "unknown element";
-                       break;
-               }
-               printk(KERN_INFO "\t(%s:%s), vol handle(0x%04x), "
-                   "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
-                   reason_str, le16_to_cpu(element->VolDevHandle),
-                   le16_to_cpu(element->PhysDiskDevHandle),
-                   element->PhysDiskNum);
-       }
-}
-#endif
-
-/**
- * _scsih_sas_ir_config_change_event - handle ir configuration change events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_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 =
-               (Mpi2EventDataIrConfigChangeList_t *)
-               fw_event->event_data;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-           && !ioc->hide_ir_msg)
-               _scsih_sas_ir_config_change_event_debug(ioc, event_data);
-
-#endif
-
-       if (ioc->shost_recovery)
-               return;
-
-       foreign_config = (le32_to_cpu(event_data->Flags) &
-           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
-
-       element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-       for (i = 0; i < event_data->NumElements; i++, element++) {
-
-               switch (element->ReasonCode) {
-               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
-               case MPI2_EVENT_IR_CHANGE_RC_ADDED:
-                       if (!foreign_config)
-                               _scsih_sas_volume_add(ioc, element);
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
-               case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
-                       if (!foreign_config)
-                               _scsih_sas_volume_delete(ioc,
-                                   le16_to_cpu(element->VolDevHandle));
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
-                       if (!ioc->is_warpdrive)
-                               _scsih_sas_pd_hide(ioc, element);
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
-                       if (!ioc->is_warpdrive)
-                               _scsih_sas_pd_expose(ioc, element);
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_HIDE:
-                       if (!ioc->is_warpdrive)
-                               _scsih_sas_pd_add(ioc, element);
-                       break;
-               case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
-                       if (!ioc->is_warpdrive)
-                               _scsih_sas_pd_delete(ioc, element);
-                       break;
-               }
-       }
-}
-
-/**
- * _scsih_sas_ir_volume_event - IR volume event
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       u64 wwid;
-       unsigned long flags;
-       struct _raid_device *raid_device;
-       u16 handle;
-       u32 state;
-       int rc;
-       Mpi2EventDataIrVolume_t *event_data =
-               (Mpi2EventDataIrVolume_t *)
-               fw_event->event_data;
-
-       if (ioc->shost_recovery)
-               return;
-
-       if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
-               return;
-
-       handle = le16_to_cpu(event_data->VolDevHandle);
-       state = le32_to_cpu(event_data->NewValue);
-       if (!ioc->hide_ir_msg)
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
-                   "old(0x%08x), new(0x%08x)\n", ioc->name, __func__,  handle,
-                   le32_to_cpu(event_data->PreviousValue), state));
-
-       switch (state) {
-       case MPI2_RAID_VOL_STATE_MISSING:
-       case MPI2_RAID_VOL_STATE_FAILED:
-               _scsih_sas_volume_delete(ioc, handle);
-               break;
-
-       case MPI2_RAID_VOL_STATE_ONLINE:
-       case MPI2_RAID_VOL_STATE_DEGRADED:
-       case MPI2_RAID_VOL_STATE_OPTIMAL:
-
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-
-               if (raid_device)
-                       break;
-
-               mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
-               if (!wwid) {
-                       printk(MPT2SAS_ERR_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name,
-                           __FILE__, __LINE__, __func__);
-                       break;
-               }
-
-               raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
-               if (!raid_device) {
-                       printk(MPT2SAS_ERR_FMT
-                           "failure at %s:%d/%s()!\n", ioc->name,
-                           __FILE__, __LINE__, __func__);
-                       break;
-               }
-
-               raid_device->id = ioc->sas_id++;
-               raid_device->channel = RAID_CHANNEL;
-               raid_device->handle = handle;
-               raid_device->wwid = wwid;
-               _scsih_raid_device_add(ioc, raid_device);
-               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
-                   raid_device->id, 0);
-               if (rc)
-                       _scsih_raid_device_remove(ioc, raid_device);
-               break;
-
-       case MPI2_RAID_VOL_STATE_INITIALIZING:
-       default:
-               break;
-       }
-}
-
-/**
- * _scsih_sas_ir_physical_disk_event - PD event
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       u16 handle, parent_handle;
-       u32 state;
-       struct _sas_device *sas_device;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       u32 ioc_status;
-       Mpi2EventDataIrPhysicalDisk_t *event_data =
-               (Mpi2EventDataIrPhysicalDisk_t *)
-               fw_event->event_data;
-       u64 sas_address;
-
-       if (ioc->shost_recovery)
-               return;
-
-       if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
-               return;
-
-       handle = le16_to_cpu(event_data->PhysDiskDevHandle);
-       state = le32_to_cpu(event_data->NewValue);
-
-       if (!ioc->hide_ir_msg)
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: handle(0x%04x), "
-                   "old(0x%08x), new(0x%08x)\n", ioc->name, __func__,  handle,
-                   le32_to_cpu(event_data->PreviousValue), state));
-
-       switch (state) {
-       case MPI2_RAID_PD_STATE_ONLINE:
-       case MPI2_RAID_PD_STATE_DEGRADED:
-       case MPI2_RAID_PD_STATE_REBUILDING:
-       case MPI2_RAID_PD_STATE_OPTIMAL:
-       case MPI2_RAID_PD_STATE_HOT_SPARE:
-
-               if (!ioc->is_warpdrive)
-                       set_bit(handle, ioc->pd_handles);
-
-               sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
-               if (sas_device) {
-                       sas_device_put(sas_device);
-                       return;
-               }
-
-               if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
-                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
-                   handle))) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       return;
-               }
-
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       return;
-               }
-
-               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
-               if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
-                       mpt2sas_transport_update_links(ioc, sas_address, handle,
-                           sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
-
-               _scsih_add_device(ioc, handle, 0, 1);
-
-               break;
-
-       case MPI2_RAID_PD_STATE_OFFLINE:
-       case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
-       case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
-       default:
-               break;
-       }
-}
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-/**
- * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
- * @ioc: per adapter object
- * @event_data: event data payload
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
-    Mpi2EventDataIrOperationStatus_t *event_data)
-{
-       char *reason_str = NULL;
-
-       switch (event_data->RAIDOperation) {
-       case MPI2_EVENT_IR_RAIDOP_RESYNC:
-               reason_str = "resync";
-               break;
-       case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
-               reason_str = "online capacity expansion";
-               break;
-       case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
-               reason_str = "consistency check";
-               break;
-       case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
-               reason_str = "background init";
-               break;
-       case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
-               reason_str = "make data consistent";
-               break;
-       }
-
-       if (!reason_str)
-               return;
-
-       printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
-           "\thandle(0x%04x), percent complete(%d)\n",
-           ioc->name, reason_str,
-           le16_to_cpu(event_data->VolDevHandle),
-           event_data->PercentComplete);
-}
-#endif
-
-/**
- * _scsih_sas_ir_operation_status_event - handle RAID operation events
- * @ioc: per adapter object
- * @fw_event: The fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc,
-    struct fw_event_work *fw_event)
-{
-       Mpi2EventDataIrOperationStatus_t *event_data =
-               (Mpi2EventDataIrOperationStatus_t *)
-               fw_event->event_data;
-       static struct _raid_device *raid_device;
-       unsigned long flags;
-       u16 handle;
-
-#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
-       if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
-           && !ioc->hide_ir_msg)
-               _scsih_sas_ir_operation_status_event_debug(ioc,
-                    event_data);
-#endif
-
-       /* code added for raid transport support */
-       if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
-
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               handle = le16_to_cpu(event_data->VolDevHandle);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
-               if (raid_device)
-                       raid_device->percent_complete =
-                           event_data->PercentComplete;
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-       }
-}
-
-/**
- * _scsih_prep_device_scan - initialize parameters prior to device scan
- * @ioc: per adapter object
- *
- * Set the deleted flag prior to device scan.  If the device is found during
- * the scan, then we clear the deleted flag.
- */
-static void
-_scsih_prep_device_scan(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct MPT2SAS_DEVICE *sas_device_priv_data;
-       struct scsi_device *sdev;
-
-       shost_for_each_device(sdev, ioc->shost) {
-               sas_device_priv_data = sdev->hostdata;
-               if (sas_device_priv_data && sas_device_priv_data->sas_target)
-                       sas_device_priv_data->sas_target->deleted = 1;
-       }
-}
-
-/**
- * _scsih_mark_responding_sas_device - mark a sas_devices as responding
- * @ioc: per adapter object
- * @sas_address: sas address
- * @slot: enclosure slot id
- * @handle: device handle
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_sas_devices.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
-    u16 slot, u16 handle)
-{
-       struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
-       struct scsi_target *starget;
-       struct _sas_device *sas_device;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
-               if (sas_device->sas_address == sas_address &&
-                   sas_device->slot == slot) {
-                       sas_device->responding = 1;
-                       starget = sas_device->starget;
-                       if (starget && starget->hostdata) {
-                               sas_target_priv_data = starget->hostdata;
-                               sas_target_priv_data->tm_busy = 0;
-                               sas_target_priv_data->deleted = 0;
-                       } else
-                               sas_target_priv_data = NULL;
-                       if (starget)
-                               starget_printk(KERN_INFO, starget,
-                                   "handle(0x%04x), sas_addr(0x%016llx), "
-                                   "enclosure logical id(0x%016llx), "
-                                   "slot(%d)\n", handle,
-                                   (unsigned long long)sas_device->sas_address,
-                                   (unsigned long long)
-                                   sas_device->enclosure_logical_id,
-                                   sas_device->slot);
-                       if (sas_device->handle == handle)
-                               goto out;
-                       printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
-                           sas_device->handle);
-                       sas_device->handle = handle;
-                       if (sas_target_priv_data)
-                               sas_target_priv_data->handle = handle;
-                       goto out;
-               }
-       }
- out:
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_search_responding_sas_devices -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 ioc_status;
-       __le64 sas_address;
-       u16 handle;
-       u32 device_info;
-       u16 slot;
-
-       printk(MPT2SAS_INFO_FMT "search for end-devices: start\n", ioc->name);
-
-       if (list_empty(&ioc->sas_device_list))
-               goto out;
-
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
-           &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
-           handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-                       break;
-               handle = le16_to_cpu(sas_device_pg0.DevHandle);
-               device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-               if (!(_scsih_is_end_device(device_info)))
-                       continue;
-               sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-               slot = le16_to_cpu(sas_device_pg0.Slot);
-               _scsih_mark_responding_sas_device(ioc, sas_address, slot,
-                   handle);
-       }
-out:
-       printk(MPT2SAS_INFO_FMT "search for end-devices: complete\n",
-           ioc->name);
-}
-
-/**
- * _scsih_mark_responding_raid_device - mark a raid_device as responding
- * @ioc: per adapter object
- * @wwid: world wide identifier for raid volume
- * @handle: device handle
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_raid_devices.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
-    u16 handle)
-{
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct scsi_target *starget;
-       struct _raid_device *raid_device;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
-               if (raid_device->wwid == wwid && raid_device->starget) {
-                       starget = raid_device->starget;
-                       if (starget && starget->hostdata) {
-                               sas_target_priv_data = starget->hostdata;
-                               sas_target_priv_data->deleted = 0;
-                       } else
-                               sas_target_priv_data = NULL;
-                       raid_device->responding = 1;
-                       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-                       starget_printk(KERN_INFO, raid_device->starget,
-                           "handle(0x%04x), wwid(0x%016llx)\n", handle,
-                           (unsigned long long)raid_device->wwid);
-                       /*
-                        * WARPDRIVE: The handles of the PDs might have changed
-                        * across the host reset so re-initialize the
-                        * required data for Direct IO
-                        */
-                       _scsih_init_warpdrive_properties(ioc, raid_device);
-                       spin_lock_irqsave(&ioc->raid_device_lock, flags);
-                       if (raid_device->handle == handle) {
-                               spin_unlock_irqrestore(&ioc->raid_device_lock,
-                                   flags);
-                               return;
-                       }
-                       printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
-                           raid_device->handle);
-                       raid_device->handle = handle;
-                       if (sas_target_priv_data)
-                               sas_target_priv_data->handle = handle;
-                       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-                       return;
-               }
-       }
-
-       spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-}
-
-/**
- * _scsih_search_responding_raid_devices -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2RaidVolPage1_t volume_pg1;
-       Mpi2RaidVolPage0_t volume_pg0;
-       Mpi2RaidPhysDiskPage0_t pd_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 ioc_status;
-       u16 handle;
-       u8 phys_disk_num;
-
-       if (!ioc->ir_firmware)
-               return;
-
-       printk(MPT2SAS_INFO_FMT "search for raid volumes: start\n",
-           ioc->name);
-
-       if (list_empty(&ioc->raid_device_list))
-               goto out;
-
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
-           &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-                       break;
-               handle = le16_to_cpu(volume_pg1.DevHandle);
-
-               if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
-                   &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
-                    sizeof(Mpi2RaidVolPage0_t)))
-                       continue;
-
-               if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
-                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
-                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
-                       _scsih_mark_responding_raid_device(ioc,
-                           le64_to_cpu(volume_pg1.WWID), handle);
-       }
-
-       /* refresh the pd_handles */
-       if (!ioc->is_warpdrive) {
-               phys_disk_num = 0xFF;
-               memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
-               while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
-                   &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
-                   phys_disk_num))) {
-                       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                           MPI2_IOCSTATUS_MASK;
-                       if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-                               break;
-                       phys_disk_num = pd_pg0.PhysDiskNum;
-                       handle = le16_to_cpu(pd_pg0.DevHandle);
-                       set_bit(handle, ioc->pd_handles);
-               }
-       }
-out:
-       printk(MPT2SAS_INFO_FMT "search for responding raid volumes: "
-           "complete\n", ioc->name);
-}
-
-/**
- * _scsih_mark_responding_expander - mark a expander as responding
- * @ioc: per adapter object
- * @sas_address: sas address
- * @handle:
- *
- * After host reset, find out whether devices are still responding.
- * Used in _scsi_remove_unresponsive_expanders.
- *
- * Return nothing.
- */
-static void
-_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
-     u16 handle)
-{
-       struct _sas_node *sas_expander;
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
-               if (sas_expander->sas_address != sas_address)
-                       continue;
-               sas_expander->responding = 1;
-               if (sas_expander->handle == handle)
-                       goto out;
-               printk(KERN_INFO "\texpander(0x%016llx): handle changed"
-                   " from(0x%04x) to (0x%04x)!!!\n",
-                   (unsigned long long)sas_expander->sas_address,
-                   sas_expander->handle, handle);
-               sas_expander->handle = handle;
-               for (i = 0 ; i < sas_expander->num_phys ; i++)
-                       sas_expander->phy[i].handle = handle;
-               goto out;
-       }
- out:
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-}
-
-/**
- * _scsih_search_responding_expanders -
- * @ioc: per adapter object
- *
- * After host reset, find out whether devices are still responding.
- * If not remove.
- *
- * Return nothing.
- */
-static void
-_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2ExpanderPage0_t expander_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 ioc_status;
-       u64 sas_address;
-       u16 handle;
-
-       printk(MPT2SAS_INFO_FMT "search for expanders: start\n", ioc->name);
-
-       if (list_empty(&ioc->sas_expander_list))
-               goto out;
-
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
-           MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
-
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
-                       break;
-
-               handle = le16_to_cpu(expander_pg0.DevHandle);
-               sas_address = le64_to_cpu(expander_pg0.SASAddress);
-               printk(KERN_INFO "\texpander present: handle(0x%04x), "
-                   "sas_addr(0x%016llx)\n", handle,
-                   (unsigned long long)sas_address);
-               _scsih_mark_responding_expander(ioc, sas_address, handle);
-       }
-
- out:
-       printk(MPT2SAS_INFO_FMT "search for expanders: complete\n", ioc->name);
-}
-
-/**
- * _scsih_remove_unresponding_sas_devices - removing unresponding devices
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct _sas_device *sas_device, *sas_device_next;
-       struct _sas_node *sas_expander, *sas_expander_next;
-       struct _raid_device *raid_device, *raid_device_next;
-       struct list_head tmp_list;
-       unsigned long flags;
-       LIST_HEAD(head);
-
-       printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n",
-           ioc->name);
-
-       /* removing unresponding end devices */
-       printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n",
-           ioc->name);
-
-       /*
-        * Iterate, pulling off devices marked as non-responding. We become the
-        * owner for the reference the list had on any object we prune.
-        */
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       list_for_each_entry_safe(sas_device, sas_device_next,
-                       &ioc->sas_device_list, list) {
-               if (!sas_device->responding)
-                       list_move_tail(&sas_device->list, &head);
-               else
-                       sas_device->responding = 0;
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       /*
-        * Now, uninitialize and remove the unresponding devices we pruned.
-        */
-       list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
-               _scsih_remove_device(ioc, sas_device);
-               list_del_init(&sas_device->list);
-               sas_device_put(sas_device);
-       }
-
-       /* removing unresponding volumes */
-       if (ioc->ir_firmware) {
-               printk(MPT2SAS_INFO_FMT "removing unresponding devices: "
-                   "volumes\n", ioc->name);
-               list_for_each_entry_safe(raid_device, raid_device_next,
-                   &ioc->raid_device_list, list) {
-                       if (!raid_device->responding)
-                               _scsih_sas_volume_delete(ioc,
-                                   raid_device->handle);
-                       else
-                               raid_device->responding = 0;
-               }
-       }
-       /* removing unresponding expanders */
-       printk(MPT2SAS_INFO_FMT "removing unresponding devices: expanders\n",
-           ioc->name);
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       INIT_LIST_HEAD(&tmp_list);
-       list_for_each_entry_safe(sas_expander, sas_expander_next,
-           &ioc->sas_expander_list, list) {
-               if (!sas_expander->responding)
-                       list_move_tail(&sas_expander->list, &tmp_list);
-               else
-                       sas_expander->responding = 0;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-       list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
-           list) {
-               list_del(&sas_expander->list);
-               _scsih_expander_node_remove(ioc, sas_expander);
-       }
-       printk(MPT2SAS_INFO_FMT "removing unresponding devices: complete\n",
-           ioc->name);
-       /* unblock devices */
-       _scsih_ublock_io_all_device(ioc);
-}
-
-static void
-_scsih_refresh_expander_links(struct MPT2SAS_ADAPTER *ioc,
-       struct _sas_node *sas_expander, u16 handle)
-{
-       Mpi2ExpanderPage1_t expander_pg1;
-       Mpi2ConfigReply_t mpi_reply;
-       int i;
-
-       for (i = 0 ; i < sas_expander->num_phys ; i++) {
-               if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
-                   &expander_pg1, i, handle))) {
-                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                           ioc->name, __FILE__, __LINE__, __func__);
-                       return;
-               }
-
-               mpt2sas_transport_update_links(ioc, sas_expander->sas_address,
-                   le16_to_cpu(expander_pg1.AttachedDevHandle), i,
-                   expander_pg1.NegotiatedLinkRate >> 4);
-       }
-}
-
-/**
- * _scsih_scan_for_devices_after_reset - scan for devices after host reset
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2ExpanderPage0_t expander_pg0;
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2RaidVolPage1_t volume_pg1;
-       Mpi2RaidVolPage0_t volume_pg0;
-       Mpi2RaidPhysDiskPage0_t pd_pg0;
-       Mpi2EventIrConfigElement_t element;
-       Mpi2ConfigReply_t mpi_reply;
-       u8 phys_disk_num;
-       u16 ioc_status;
-       u16 handle, parent_handle;
-       u64 sas_address;
-       struct _sas_device *sas_device;
-       struct _sas_node *expander_device;
-       static struct _raid_device *raid_device;
-       u8 retry_count;
-       unsigned long flags;
-
-       printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
-
-       _scsih_sas_host_refresh(ioc);
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
-               ioc->name);
-       /* expanders */
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
-           MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
-                               "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                       break;
-               }
-               handle = le16_to_cpu(expander_pg0.DevHandle);
-               spin_lock_irqsave(&ioc->sas_node_lock, flags);
-               expander_device = mpt2sas_scsih_expander_find_by_sas_address(
-                   ioc, le64_to_cpu(expander_pg0.SASAddress));
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               if (expander_device)
-                       _scsih_refresh_expander_links(ioc, expander_device,
-                           handle);
-               else {
-                       printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
-                               "handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(expander_pg0.SASAddress));
-                       _scsih_expander_add(ioc, handle);
-                       printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
-                               "handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(expander_pg0.SASAddress));
-               }
-       }
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
-               ioc->name);
-
-       if (!ioc->ir_firmware)
-               goto skip_to_sas;
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
-       /* phys disk */
-       phys_disk_num = 0xFF;
-       while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
-           &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
-           phys_disk_num))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
-                               "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                       break;
-               }
-               phys_disk_num = pd_pg0.PhysDiskNum;
-               handle = le16_to_cpu(pd_pg0.DevHandle);
-               sas_device = mpt2sas_get_sdev_by_handle(ioc, handle);
-               if (sas_device) {
-                       sas_device_put(sas_device);
-                       continue;
-               }
-               if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
-                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
-                   handle) != 0)
-                       continue;
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                       MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
-                               "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                       break;
-               }
-               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
-               if (!_scsih_get_sas_address(ioc, parent_handle,
-                   &sas_address)) {
-                       printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
-                               " handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(sas_device_pg0.SASAddress));
-                       mpt2sas_transport_update_links(ioc, sas_address,
-                           handle, sas_device_pg0.PhyNum,
-                           MPI2_SAS_NEG_LINK_RATE_1_5);
-                       set_bit(handle, ioc->pd_handles);
-                       retry_count = 0;
-                       /* This will retry adding the end device.
-                       * _scsih_add_device() will decide on retries and
-                       * return "1" when it should be retried
-                       */
-                       while (_scsih_add_device(ioc, handle, retry_count++,
-                               1)) {
-                                       ssleep(1);
-                       }
-                       printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
-                               " handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(sas_device_pg0.SASAddress));
-               }
-       }
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
-               ioc->name);
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
-       /* volumes */
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
-           &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
-                               "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                       break;
-               }
-               handle = le16_to_cpu(volume_pg1.DevHandle);
-               spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_wwid(ioc,
-                   le64_to_cpu(volume_pg1.WWID));
-               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
-               if (raid_device)
-                       continue;
-               if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
-                   &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
-                    sizeof(Mpi2RaidVolPage0_t)))
-                       continue;
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                       MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
-                               "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                       break;
-               }
-               if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
-                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
-                   volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
-                       memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
-                       element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
-                       element.VolDevHandle = volume_pg1.DevHandle;
-                       printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
-                               " handle (0x%04x)\n", ioc->name,
-                               volume_pg1.DevHandle);
-                       _scsih_sas_volume_add(ioc, &element);
-                       printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
-                               " handle (0x%04x)\n", ioc->name,
-                               volume_pg1.DevHandle);
-               }
-       }
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
-               ioc->name);
-
- skip_to_sas:
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
-               ioc->name);
-       /* sas devices */
-       handle = 0xFFFF;
-       while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
-           &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
-           handle))) {
-               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-                   MPI2_IOCSTATUS_MASK;
-               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-                       printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
-                               " ioc_status(0x%04x), loginfo(0x%08x)\n",
-                               ioc->name, ioc_status,
-                               le32_to_cpu(mpi_reply.IOCLogInfo));
-                               break;
-               }
-               handle = le16_to_cpu(sas_device_pg0.DevHandle);
-               if (!(_scsih_is_end_device(
-                   le32_to_cpu(sas_device_pg0.DeviceInfo))))
-                       continue;
-               sas_device = mpt2sas_get_sdev_by_addr(ioc,
-                   le64_to_cpu(sas_device_pg0.SASAddress));
-               if (sas_device) {
-                       sas_device_put(sas_device);
-                       continue;
-               }
-               parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
-               if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
-                       printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
-                               "handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(sas_device_pg0.SASAddress));
-                       mpt2sas_transport_update_links(ioc, sas_address, handle,
-                           sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
-                       retry_count = 0;
-                       /* This will retry adding the end device.
-                        * _scsih_add_device() will decide on retries and
-                        * return "1" when it should be retried
-                        */
-                       while (_scsih_add_device(ioc, handle, retry_count++,
-                               0)) {
-                                       ssleep(1);
-                       }
-                       printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
-                               "handle (0x%04x), sas_addr(0x%016llx)\n",
-                               ioc->name, handle, (unsigned long long)
-                               le64_to_cpu(sas_device_pg0.SASAddress));
-               }
-       }
-
-       printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
-               ioc->name);
-
-       printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
-}
-
-
-/**
- * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
- * @ioc: per adapter object
- * @reset_phase: phase
- *
- * The handler for doing any required cleanup or initialization.
- *
- * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
- * MPT2_IOC_DONE_RESET
- *
- * Return nothing.
- */
-void
-mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
-{
-       switch (reset_phase) {
-       case MPT2_IOC_PRE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
-               break;
-       case MPT2_IOC_AFTER_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
-               if (ioc->scsih_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->scsih_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
-                       complete(&ioc->scsih_cmds.done);
-               }
-               if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
-                       ioc->tm_cmds.status |= MPT2_CMD_RESET;
-                       mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
-                       complete(&ioc->tm_cmds.done);
-               }
-               _scsih_fw_event_cleanup_queue(ioc);
-               _scsih_flush_running_cmds(ioc);
-               break;
-       case MPT2_IOC_DONE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-                   "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
-               _scsih_sas_host_refresh(ioc);
-               _scsih_prep_device_scan(ioc);
-               _scsih_search_responding_sas_devices(ioc);
-               _scsih_search_responding_raid_devices(ioc);
-               _scsih_search_responding_expanders(ioc);
-               if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
-                   !ioc->sas_hba.num_phys)) {
-                       _scsih_prep_device_scan(ioc);
-                       _scsih_search_responding_sas_devices(ioc);
-                       _scsih_search_responding_raid_devices(ioc);
-                       _scsih_search_responding_expanders(ioc);
-                       _scsih_error_recovery_delete_devices(ioc);
-               }
-               break;
-       }
-}
-
-/**
- * _firmware_event_work - delayed task for processing firmware events
- * @ioc: per adapter object
- * @work: equal to the fw_event_work object
- * Context: user.
- *
- * Return nothing.
- */
-static void
-_firmware_event_work(struct work_struct *work)
-{
-       struct fw_event_work *fw_event = container_of(work,
-           struct fw_event_work, delayed_work.work);
-       struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
-
-       _scsih_fw_event_del_from_list(ioc, fw_event);
-
-       /* the queue is being flushed so ignore this event */
-       if (ioc->remove_host || ioc->pci_error_recovery) {
-               fw_event_work_put(fw_event);
-               return;
-       }
-
-       switch (fw_event->event) {
-       case MPT2SAS_REMOVE_UNRESPONDING_DEVICES:
-               while (scsi_host_in_recovery(ioc->shost) ||
-                               ioc->shost_recovery) {
-                       /*
-                        * If we're unloading, bail. Otherwise, this can become
-                        * an infinite loop.
-                        */
-                       if (ioc->remove_host)
-                               goto out;
-
-                       ssleep(1);
-               }
-               _scsih_remove_unresponding_sas_devices(ioc);
-               _scsih_scan_for_devices_after_reset(ioc);
-               break;
-       case MPT2SAS_PORT_ENABLE_COMPLETE:
-               ioc->start_scan = 0;
-
-               if (missing_delay[0] != -1 && missing_delay[1] != -1)
-                       mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
-                               missing_delay[1]);
-
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
-                   "from worker thread\n", ioc->name));
-               break;
-       case MPT2SAS_TURN_ON_PFA_LED:
-               _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
-               break;
-       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
-               _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);
-               break;
-       case MPI2_EVENT_SAS_DISCOVERY:
-               _scsih_sas_discovery_event(ioc,
-                   fw_event);
-               break;
-       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
-               _scsih_sas_broadcast_primitive_event(ioc,
-                   fw_event);
-               break;
-       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
-               _scsih_sas_enclosure_dev_status_change_event(ioc,
-                   fw_event);
-               break;
-       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
-               _scsih_sas_ir_config_change_event(ioc, fw_event);
-               break;
-       case MPI2_EVENT_IR_VOLUME:
-               _scsih_sas_ir_volume_event(ioc, fw_event);
-               break;
-       case MPI2_EVENT_IR_PHYSICAL_DISK:
-               _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);
-               break;
-       }
-out:
-       fw_event_work_put(fw_event);
-}
-
-/**
- * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
- * @ioc: per adapter object
- * @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.
- *
- * Returns void.
- */
-void
-mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index,
-       u32 reply)
-{
-       struct fw_event_work *fw_event;
-       Mpi2EventNotificationReply_t *mpi_reply;
-       u16 event;
-       u16 sz;
-
-       /* events turned off due to host reset or driver unloading */
-       if (ioc->remove_host || ioc->pci_error_recovery)
-               return;
-
-       mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
-
-       if (unlikely(!mpi_reply)) {
-               printk(MPT2SAS_ERR_FMT "mpi_reply not valid at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       event = le16_to_cpu(mpi_reply->Event);
-
-       switch (event) {
-       /* handle these */
-       case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
-       {
-               Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
-                   (Mpi2EventDataSasBroadcastPrimitive_t *)
-                   mpi_reply->EventData;
-
-               if (baen_data->Primitive !=
-                   MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
-                       return;
-
-               if (ioc->broadcast_aen_busy) {
-                       ioc->broadcast_aen_pending++;
-                       return;
-               } else
-                       ioc->broadcast_aen_busy = 1;
-               break;
-       }
-
-       case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
-               _scsih_check_topo_delete_events(ioc,
-                   (Mpi2EventDataSasTopologyChangeList_t *)
-                   mpi_reply->EventData);
-               break;
-       case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
-               _scsih_check_ir_config_unhide_events(ioc,
-                   (Mpi2EventDataIrConfigChangeList_t *)
-                   mpi_reply->EventData);
-               break;
-       case MPI2_EVENT_IR_VOLUME:
-               _scsih_check_volume_delete_events(ioc,
-                   (Mpi2EventDataIrVolume_t *)
-                   mpi_reply->EventData);
-               break;
-       case MPI2_EVENT_LOG_ENTRY_ADDED:
-       {
-               Mpi2EventDataLogEntryAdded_t *log_entry;
-               __le32 *log_code;
-
-               if (!ioc->is_warpdrive)
-                       break;
-
-               log_entry = (Mpi2EventDataLogEntryAdded_t *)
-                   mpi_reply->EventData;
-               log_code = (__le32 *)log_entry->LogData;
-
-               if (le16_to_cpu(log_entry->LogEntryQualifier)
-                   != MPT2_WARPDRIVE_LOGENTRY)
-                       break;
-
-               switch (le32_to_cpu(*log_code)) {
-               case MPT2_WARPDRIVE_LC_SSDT:
-                       printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
-                           "IO Throttling has occurred in the WarpDrive "
-                           "subsystem. Check WarpDrive documentation for "
-                           "additional details.\n", ioc->name);
-                       break;
-               case MPT2_WARPDRIVE_LC_SSDLW:
-                       printk(MPT2SAS_WARN_FMT "WarpDrive Warning: "
-                           "Program/Erase Cycles for the WarpDrive subsystem "
-                           "in degraded range. Check WarpDrive documentation "
-                           "for additional details.\n", ioc->name);
-                       break;
-               case MPT2_WARPDRIVE_LC_SSDLF:
-                       printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
-                           "There are no Program/Erase Cycles for the "
-                           "WarpDrive subsystem. The storage device will be "
-                           "in read-only mode. Check WarpDrive documentation "
-                           "for additional details.\n", ioc->name);
-                       break;
-               case MPT2_WARPDRIVE_LC_BRMF:
-                       printk(MPT2SAS_ERR_FMT "WarpDrive Fatal Error: "
-                           "The Backup Rail Monitor has failed on the "
-                           "WarpDrive subsystem. Check WarpDrive "
-                           "documentation for additional details.\n",
-                           ioc->name);
-                       break;
-               }
-
-               break;
-       }
-       case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
-       case MPI2_EVENT_IR_OPERATION_STATUS:
-       case MPI2_EVENT_SAS_DISCOVERY:
-       case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
-       case MPI2_EVENT_IR_PHYSICAL_DISK:
-               break;
-
-       case MPI2_EVENT_TEMP_THRESHOLD:
-               _scsih_temp_threshold_events(ioc,
-                       (Mpi2EventDataTemperature_t *)
-                       mpi_reply->EventData);
-               break;
-
-       default: /* ignore the rest */
-               return;
-       }
-
-       sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-       fw_event = alloc_fw_event_work(sz);
-       if (!fw_event) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return;
-       }
-
-       memcpy(fw_event->event_data, mpi_reply->EventData, sz);
-       fw_event->ioc = ioc;
-       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);
-       fw_event_work_put(fw_event);
-       return;
-}
-
-/* shost template */
-static struct scsi_host_template scsih_driver_template = {
-       .module                         = THIS_MODULE,
-       .name                           = "Fusion MPT SAS Host",
-       .proc_name                      = MPT2SAS_DRIVER_NAME,
-       .queuecommand                   = _scsih_qcmd,
-       .target_alloc                   = _scsih_target_alloc,
-       .slave_alloc                    = _scsih_slave_alloc,
-       .slave_configure                = _scsih_slave_configure,
-       .target_destroy                 = _scsih_target_destroy,
-       .slave_destroy                  = _scsih_slave_destroy,
-       .scan_finished                  = _scsih_scan_finished,
-       .scan_start                     = _scsih_scan_start,
-       .change_queue_depth             = _scsih_change_queue_depth,
-       .eh_abort_handler               = _scsih_abort,
-       .eh_device_reset_handler        = _scsih_dev_reset,
-       .eh_target_reset_handler        = _scsih_target_reset,
-       .eh_host_reset_handler          = _scsih_host_reset,
-       .bios_param                     = _scsih_bios_param,
-       .can_queue                      = 1,
-       .this_id                        = -1,
-       .sg_tablesize                   = MPT2SAS_SG_DEPTH,
-       .max_sectors                    = 32767,
-       .cmd_per_lun                    = 7,
-       .use_clustering                 = ENABLE_CLUSTERING,
-       .shost_attrs                    = mpt2sas_host_attrs,
-       .sdev_attrs                     = mpt2sas_dev_attrs,
-       .track_queue_depth              = 1,
-};
-
-/**
- * _scsih_expander_node_remove - removing expander device from list.
- * @ioc: per adapter object
- * @sas_expander: the sas_device object
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * Removing object and freeing associated memory from the
- * ioc->sas_expander_list.
- *
- * Return nothing.
- */
-static void
-_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
-    struct _sas_node *sas_expander)
-{
-       struct _sas_port *mpt2sas_port, *next;
-
-       /* remove sibling ports attached to this expander */
-       list_for_each_entry_safe(mpt2sas_port, next,
-          &sas_expander->sas_port_list, port_list) {
-               if (ioc->shost_recovery)
-                       return;
-               if (mpt2sas_port->remote_identify.device_type ==
-                   SAS_END_DEVICE)
-                       mpt2sas_device_remove_by_sas_address(ioc,
-                           mpt2sas_port->remote_identify.sas_address);
-               else if (mpt2sas_port->remote_identify.device_type ==
-                   SAS_EDGE_EXPANDER_DEVICE ||
-                   mpt2sas_port->remote_identify.device_type ==
-                   SAS_FANOUT_EXPANDER_DEVICE)
-                       mpt2sas_expander_remove(ioc,
-                           mpt2sas_port->remote_identify.sas_address);
-       }
-
-       mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
-           sas_expander->sas_address_parent);
-
-       printk(MPT2SAS_INFO_FMT "expander_remove: handle"
-          "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
-           sas_expander->handle, (unsigned long long)
-           sas_expander->sas_address);
-
-       kfree(sas_expander->phy);
-       kfree(sas_expander);
-}
-
-/**
- * _scsih_ir_shutdown - IR shutdown notification
- * @ioc: per adapter object
- *
- * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
- * the host system is shutting down.
- *
- * Return nothing.
- */
-static void
-_scsih_ir_shutdown(struct MPT2SAS_ADAPTER *ioc)
-{
-       Mpi2RaidActionRequest_t *mpi_request;
-       Mpi2RaidActionReply_t *mpi_reply;
-       u16 smid;
-
-       /* is IR firmware build loaded ? */
-       if (!ioc->ir_firmware)
-               return;
-
-       mutex_lock(&ioc->scsih_cmds.mutex);
-
-       if (ioc->scsih_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: scsih_cmd in use\n",
-                   ioc->name, __func__);
-               goto out;
-       }
-       ioc->scsih_cmds.status = MPT2_CMD_PENDING;
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->scsih_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
-               goto out;
-       }
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->scsih_cmds.smid = smid;
-       memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
-
-       mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
-       mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
-
-       if (!ioc->hide_ir_msg)
-               printk(MPT2SAS_INFO_FMT "IR shutdown (sending)\n", ioc->name);
-       init_completion(&ioc->scsih_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
-
-       if (!(ioc->scsih_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               goto out;
-       }
-
-       if (ioc->scsih_cmds.status & MPT2_CMD_REPLY_VALID) {
-               mpi_reply = ioc->scsih_cmds.reply;
-
-               if (!ioc->hide_ir_msg)
-                       printk(MPT2SAS_INFO_FMT "IR shutdown (complete): "
-                           "ioc_status(0x%04x), loginfo(0x%08x)\n",
-                           ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
-                           le32_to_cpu(mpi_reply->IOCLogInfo));
-       }
-
- out:
-       ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_unlock(&ioc->scsih_cmds.mutex);
-}
-
-/**
- * _scsih_shutdown - routine call during system shutdown
- * @pdev: PCI device struct
- *
- * Return nothing.
- */
-static void
-_scsih_shutdown(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct workqueue_struct *wq;
-       unsigned long flags;
-
-       ioc->remove_host = 1;
-       _scsih_fw_event_cleanup_queue(ioc);
-
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       wq = ioc->firmware_event_thread;
-       ioc->firmware_event_thread = NULL;
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-       if (wq)
-               destroy_workqueue(wq);
-
-       _scsih_ir_shutdown(ioc);
-       mpt2sas_base_detach(ioc);
-}
-
-/**
- * _scsih_remove - detach and remove add host
- * @pdev: PCI device struct
- *
- * Routine called when unloading the driver.
- * Return nothing.
- */
-static void
-_scsih_remove(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       struct _sas_port *mpt2sas_port, *next_port;
-       struct _raid_device *raid_device, *next;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
-       struct workqueue_struct *wq;
-       unsigned long flags;
-
-       ioc->remove_host = 1;
-       _scsih_fw_event_cleanup_queue(ioc);
-
-       spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       wq = ioc->firmware_event_thread;
-       ioc->firmware_event_thread = NULL;
-       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
-       if (wq)
-               destroy_workqueue(wq);
-
-       /* release all the volumes */
-       _scsih_ir_shutdown(ioc);
-       list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
-           list) {
-               if (raid_device->starget) {
-                       sas_target_priv_data =
-                           raid_device->starget->hostdata;
-                       sas_target_priv_data->deleted = 1;
-                       scsi_remove_target(&raid_device->starget->dev);
-               }
-               printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), wwid"
-                   "(0x%016llx)\n", ioc->name,  raid_device->handle,
-                   (unsigned long long) raid_device->wwid);
-               _scsih_raid_device_remove(ioc, raid_device);
-       }
-
-       /* free ports attached to the sas_host */
-       list_for_each_entry_safe(mpt2sas_port, next_port,
-          &ioc->sas_hba.sas_port_list, port_list) {
-               if (mpt2sas_port->remote_identify.device_type ==
-                   SAS_END_DEVICE)
-                       mpt2sas_device_remove_by_sas_address(ioc,
-                           mpt2sas_port->remote_identify.sas_address);
-               else if (mpt2sas_port->remote_identify.device_type ==
-                   SAS_EDGE_EXPANDER_DEVICE ||
-                   mpt2sas_port->remote_identify.device_type ==
-                   SAS_FANOUT_EXPANDER_DEVICE)
-                       mpt2sas_expander_remove(ioc,
-                           mpt2sas_port->remote_identify.sas_address);
-       }
-
-       /* free phys attached to the sas_host */
-       if (ioc->sas_hba.num_phys) {
-               kfree(ioc->sas_hba.phy);
-               ioc->sas_hba.phy = NULL;
-               ioc->sas_hba.num_phys = 0;
-       }
-
-       sas_remove_host(shost);
-       scsi_remove_host(shost);
-       mpt2sas_base_detach(ioc);
-       spin_lock(&gioc_lock);
-       list_del(&ioc->list);
-       spin_unlock(&gioc_lock);
-       scsi_host_put(shost);
-}
-
-/**
- * _scsih_probe_boot_devices - reports 1st device
- * @ioc: per adapter object
- *
- * If specified in bios page 2, this routine reports the 1st
- * device scsi-ml or sas transport for persistent boot device
- * purposes.  Please refer to function _scsih_determine_boot_device()
- */
-static void
-_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       u8 is_raid;
-       void *device;
-       struct _sas_device *sas_device;
-       struct _raid_device *raid_device;
-       u16 handle;
-       u64 sas_address_parent;
-       u64 sas_address;
-       unsigned long flags;
-       int rc;
-
-        /* no Bios, return immediately */
-       if (!ioc->bios_pg3.BiosVersion)
-               return;
-
-       device = NULL;
-       is_raid = 0;
-       if (ioc->req_boot_device.device) {
-               device =  ioc->req_boot_device.device;
-               is_raid = ioc->req_boot_device.is_raid;
-       } else if (ioc->req_alt_boot_device.device) {
-               device =  ioc->req_alt_boot_device.device;
-               is_raid = ioc->req_alt_boot_device.is_raid;
-       } else if (ioc->current_boot_device.device) {
-               device =  ioc->current_boot_device.device;
-               is_raid = ioc->current_boot_device.is_raid;
-       }
-
-       if (!device)
-               return;
-
-       if (is_raid) {
-               raid_device = device;
-               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
-                   raid_device->id, 0);
-               if (rc)
-                       _scsih_raid_device_remove(ioc, raid_device);
-       } else {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = device;
-               handle = sas_device->handle;
-               sas_address_parent = sas_device->sas_address_parent;
-               sas_address = sas_device->sas_address;
-               list_move_tail(&sas_device->list, &ioc->sas_device_list);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-               if (ioc->hide_drives)
-                       return;
-               if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
-                   sas_device->sas_address_parent)) {
-                       _scsih_sas_device_remove(ioc, sas_device);
-               } else if (!sas_device->starget) {
-                       if (!ioc->is_driver_loading) {
-                               mpt2sas_transport_port_remove(ioc,
-                                       sas_address,
-                                       sas_address_parent);
-                               _scsih_sas_device_remove(ioc, sas_device);
-                       }
-               }
-       }
-}
-
-/**
- * _scsih_probe_raid - reporting raid volumes to scsi-ml
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct _raid_device *raid_device, *raid_next;
-       int rc;
-
-       list_for_each_entry_safe(raid_device, raid_next,
-           &ioc->raid_device_list, list) {
-               if (raid_device->starget)
-                       continue;
-               rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
-                   raid_device->id, 0);
-               if (rc)
-                       _scsih_raid_device_remove(ioc, raid_device);
-       }
-}
-
-static struct _sas_device *get_next_sas_device(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct _sas_device *sas_device = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       if (!list_empty(&ioc->sas_device_init_list)) {
-               sas_device = list_first_entry(&ioc->sas_device_init_list,
-                               struct _sas_device, list);
-               sas_device_get(sas_device);
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       return sas_device;
-}
-
-static void sas_device_make_active(struct MPT2SAS_ADAPTER *ioc,
-               struct _sas_device *sas_device)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-
-       /*
-        * Since we dropped the lock during the call to port_add(), we need to
-        * be careful here that somebody else didn't move or delete this item
-        * while we were busy with other things.
-        *
-        * If it was on the list, we need a put() for the reference the list
-        * had. Either way, we need a get() for the destination list.
-        */
-       if (!list_empty(&sas_device->list)) {
-               list_del_init(&sas_device->list);
-               sas_device_put(sas_device);
-       }
-
-       sas_device_get(sas_device);
-       list_add_tail(&sas_device->list, &ioc->sas_device_list);
-
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-}
-
-/**
- * _scsih_probe_sas - reporting sas devices to sas transport
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
-{
-       struct _sas_device *sas_device;
-
-       if (ioc->hide_drives)
-               return;
-
-       while ((sas_device = get_next_sas_device(ioc))) {
-               if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
-                               sas_device->sas_address_parent)) {
-                       _scsih_sas_device_remove(ioc, sas_device);
-                       sas_device_put(sas_device);
-                       continue;
-               } else if (!sas_device->starget) {
-                       if (!ioc->is_driver_loading) {
-                               mpt2sas_transport_port_remove(ioc,
-                                               sas_device->sas_address,
-                                               sas_device->sas_address_parent);
-                               _scsih_sas_device_remove(ioc, sas_device);
-                               sas_device_put(sas_device);
-                               continue;
-                       }
-               }
-
-               sas_device_make_active(ioc, sas_device);
-               sas_device_put(sas_device);
-       }
-}
-
-/**
- * _scsih_probe_devices - probing for devices
- * @ioc: per adapter object
- *
- * Called during initial loading of the driver.
- */
-static void
-_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
-{
-       u16 volume_mapping_flags;
-
-       if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
-               return;  /* return when IOC doesn't support initiator mode */
-
-       _scsih_probe_boot_devices(ioc);
-
-       if (ioc->ir_firmware) {
-               volume_mapping_flags =
-                   le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
-                   MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
-               if (volume_mapping_flags ==
-                   MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
-                       _scsih_probe_raid(ioc);
-                       _scsih_probe_sas(ioc);
-               } else {
-                       _scsih_probe_sas(ioc);
-                       _scsih_probe_raid(ioc);
-               }
-       } else
-               _scsih_probe_sas(ioc);
-}
-
-
-/**
- * _scsih_scan_start - scsi lld callback for .scan_start
- * @shost: SCSI host pointer
- *
- * The shost has the ability to discover targets on its own instead
- * of scanning the entire bus.  In our implemention, we will kick off
- * firmware discovery.
- */
-static void
-_scsih_scan_start(struct Scsi_Host *shost)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       int rc;
-
-       if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
-               mpt2sas_enable_diag_buffer(ioc, diag_buffer_enable);
-
-       if (disable_discovery > 0)
-               return;
-
-       ioc->start_scan = 1;
-       rc = mpt2sas_port_enable(ioc);
-
-       if (rc != 0)
-               printk(MPT2SAS_INFO_FMT "port enable: FAILED\n", ioc->name);
-}
-
-/**
- * _scsih_scan_finished - scsi lld callback for .scan_finished
- * @shost: SCSI host pointer
- * @time: elapsed time of the scan in jiffies
- *
- * This function will be called periodically until it returns 1 with the
- * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
- * we wait for firmware discovery to complete, then return 1.
- */
-static int
-_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       if (disable_discovery > 0) {
-               ioc->is_driver_loading = 0;
-               ioc->wait_for_discovery_to_complete = 0;
-               return 1;
-       }
-
-       if (time >= (300 * HZ)) {
-               ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-               printk(MPT2SAS_INFO_FMT "port enable: FAILED with timeout "
-                   "(timeout=300s)\n", ioc->name);
-               ioc->is_driver_loading = 0;
-               return 1;
-       }
-
-       if (ioc->start_scan)
-               return 0;
-
-       if (ioc->start_scan_failed) {
-               printk(MPT2SAS_INFO_FMT "port enable: FAILED with "
-                   "(ioc_status=0x%08x)\n", ioc->name, ioc->start_scan_failed);
-               ioc->is_driver_loading = 0;
-               ioc->wait_for_discovery_to_complete = 0;
-               ioc->remove_host = 1;
-               return 1;
-       }
-
-       printk(MPT2SAS_INFO_FMT "port enable: SUCCESS\n", ioc->name);
-       ioc->base_cmds.status = MPT2_CMD_NOT_USED;
-
-       if (ioc->wait_for_discovery_to_complete) {
-               ioc->wait_for_discovery_to_complete = 0;
-               _scsih_probe_devices(ioc);
-       }
-       mpt2sas_base_start_watchdog(ioc);
-       ioc->is_driver_loading = 0;
-       return 1;
-}
-
-
-/**
- * _scsih_probe - attach and add scsi host
- * @pdev: PCI device struct
- * @id: pci device id
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct MPT2SAS_ADAPTER *ioc;
-       struct Scsi_Host *shost;
-       int rv;
-
-       shost = scsi_host_alloc(&scsih_driver_template,
-           sizeof(struct MPT2SAS_ADAPTER));
-       if (!shost)
-               return -ENODEV;
-
-       /* init local params */
-       ioc = shost_priv(shost);
-       memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
-       INIT_LIST_HEAD(&ioc->list);
-       spin_lock(&gioc_lock);
-       list_add_tail(&ioc->list, &mpt2sas_ioc_list);
-       spin_unlock(&gioc_lock);
-       ioc->shost = shost;
-       ioc->id = mpt_ids++;
-       sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
-       ioc->pdev = pdev;
-       if (id->device == MPI2_MFGPAGE_DEVID_SSS6200) {
-               ioc->is_warpdrive = 1;
-               ioc->hide_ir_msg = 1;
-       } else
-               ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
-       ioc->scsi_io_cb_idx = scsi_io_cb_idx;
-       ioc->tm_cb_idx = tm_cb_idx;
-       ioc->ctl_cb_idx = ctl_cb_idx;
-       ioc->base_cb_idx = base_cb_idx;
-       ioc->port_enable_cb_idx = port_enable_cb_idx;
-       ioc->transport_cb_idx = transport_cb_idx;
-       ioc->scsih_cb_idx = scsih_cb_idx;
-       ioc->config_cb_idx = config_cb_idx;
-       ioc->tm_tr_cb_idx = tm_tr_cb_idx;
-       ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
-       ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
-       ioc->logging_level = logging_level;
-       ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
-       /* misc semaphores and spin locks */
-       mutex_init(&ioc->reset_in_progress_mutex);
-       /* initializing pci_access_mutex lock */
-       mutex_init(&ioc->pci_access_mutex);
-       spin_lock_init(&ioc->ioc_reset_in_progress_lock);
-       spin_lock_init(&ioc->scsi_lookup_lock);
-       spin_lock_init(&ioc->sas_device_lock);
-       spin_lock_init(&ioc->sas_node_lock);
-       spin_lock_init(&ioc->fw_event_lock);
-       spin_lock_init(&ioc->raid_device_lock);
-
-       INIT_LIST_HEAD(&ioc->sas_device_list);
-       INIT_LIST_HEAD(&ioc->sas_device_init_list);
-       INIT_LIST_HEAD(&ioc->sas_expander_list);
-       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_LIST_HEAD(&ioc->delayed_tr_volume_list);
-       INIT_LIST_HEAD(&ioc->reply_queue_list);
-
-       /* init shost parameters */
-       shost->max_cmd_len = 32;
-       shost->max_lun = max_lun;
-       shost->transportt = mpt2sas_transport_template;
-       shost->unique_id = ioc->id;
-
-       if (max_sectors != 0xFFFF) {
-               if (max_sectors < 64) {
-                       shost->max_sectors = 64;
-                       printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
-                           "for max_sectors, range is 64 to 32767. Assigning "
-                           "value of 64.\n", ioc->name, max_sectors);
-               } else if (max_sectors > 32767) {
-                       shost->max_sectors = 32767;
-                       printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
-                           "for max_sectors, range is 64 to 8192. Assigning "
-                           "default value of 32767.\n", ioc->name,
-                           max_sectors);
-               } else {
-                       shost->max_sectors = max_sectors & 0xFFFE;
-                       printk(MPT2SAS_INFO_FMT "The max_sectors value is "
-                           "set to %d\n", ioc->name, shost->max_sectors);
-               }
-       }
-
-       /* register EEDP capabilities with SCSI layer */
-       if (prot_mask)
-               scsi_host_set_prot(shost, prot_mask);
-       else
-               scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
-                                  | SHOST_DIF_TYPE2_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),
-           "fw_event%d", ioc->id);
-       ioc->firmware_event_thread = create_singlethread_workqueue(
-           ioc->firmware_event_name);
-       if (!ioc->firmware_event_thread) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rv = -ENODEV;
-               goto out_thread_fail;
-       }
-
-       ioc->is_driver_loading = 1;
-       if ((mpt2sas_base_attach(ioc))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rv = -ENODEV;
-               goto out_attach_fail;
-       }
-
-       if (ioc->is_warpdrive) {
-               if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_EXPOSE_ALL_DISKS)
-                       ioc->hide_drives = 0;
-               else if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_HIDE_ALL_DISKS)
-                       ioc->hide_drives = 1;
-               else {
-                       if (_scsih_get_num_volumes(ioc))
-                               ioc->hide_drives = 1;
-                       else
-                               ioc->hide_drives = 0;
-               }
-       } else
-               ioc->hide_drives = 0;
-
-       rv = scsi_add_host(shost, &pdev->dev);
-       if (rv) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out_add_shost_fail;
-       }
-
-       scsi_scan_host(shost);
-
-       return 0;
-
- out_add_shost_fail:
-       mpt2sas_base_detach(ioc);
- out_attach_fail:
-       destroy_workqueue(ioc->firmware_event_thread);
- out_thread_fail:
-       spin_lock(&gioc_lock);
-       list_del(&ioc->list);
-       spin_unlock(&gioc_lock);
-       scsi_host_put(shost);
-       return rv;
-}
-
-#ifdef CONFIG_PM
-/**
- * _scsih_suspend - power management suspend main entry point
- * @pdev: PCI device struct
- * @state: PM state change to (usually PCI_D3)
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       pci_power_t device_state;
-
-       mpt2sas_base_stop_watchdog(ioc);
-       scsi_block_requests(shost);
-       _scsih_ir_shutdown(ioc);
-       device_state = pci_choose_state(pdev, state);
-       printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
-           "operating state [D%d]\n", ioc->name, pdev,
-           pci_name(pdev), device_state);
-
-       mpt2sas_base_free_resources(ioc);
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, device_state);
-       return 0;
-}
-
-/**
- * _scsih_resume - power management resume main entry point
- * @pdev: PCI device struct
- *
- * Returns 0 success, anything else error.
- */
-static int
-_scsih_resume(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       pci_power_t device_state = pdev->current_state;
-       int r;
-
-       printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
-           "operating state [D%d]\n", ioc->name, pdev,
-           pci_name(pdev), device_state);
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_enable_wake(pdev, PCI_D0, 0);
-       pci_restore_state(pdev);
-       ioc->pdev = pdev;
-       r = mpt2sas_base_map_resources(ioc);
-       if (r)
-               return r;
-
-       mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
-       scsi_unblock_requests(shost);
-       mpt2sas_base_start_watchdog(ioc);
-       return 0;
-}
-#endif /* CONFIG_PM */
-
-/**
- * _scsih_pci_error_detected - Called when a PCI error is detected.
- * @pdev: PCI device struct
- * @state: PCI channel state
- *
- * Description: Called when a PCI error is detected.
- *
- * Return value:
- *      PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
- */
-static pci_ers_result_t
-_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       printk(MPT2SAS_INFO_FMT "PCI error: detected callback, state(%d)!!\n",
-           ioc->name, state);
-
-       switch (state) {
-       case pci_channel_io_normal:
-               return PCI_ERS_RESULT_CAN_RECOVER;
-       case pci_channel_io_frozen:
-               /* Fatal error, prepare for slot reset */
-               ioc->pci_error_recovery = 1;
-               scsi_block_requests(ioc->shost);
-               mpt2sas_base_stop_watchdog(ioc);
-               mpt2sas_base_free_resources(ioc);
-               return PCI_ERS_RESULT_NEED_RESET;
-       case pci_channel_io_perm_failure:
-               /* Permanent error, prepare for device removal */
-               ioc->pci_error_recovery = 1;
-               mpt2sas_base_stop_watchdog(ioc);
-               _scsih_flush_running_cmds(ioc);
-               return PCI_ERS_RESULT_DISCONNECT;
-       }
-       return PCI_ERS_RESULT_NEED_RESET;
-}
-
-/**
- * _scsih_pci_slot_reset - Called when PCI slot has been reset.
- * @pdev: PCI device struct
- *
- * Description: This routine is called by the pci error recovery
- * code after the PCI slot has been reset, just before we
- * should resume normal operations.
- */
-static pci_ers_result_t
-_scsih_pci_slot_reset(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       int rc;
-
-       printk(MPT2SAS_INFO_FMT "PCI error: slot reset callback!!\n",
-               ioc->name);
-
-       ioc->pci_error_recovery = 0;
-       ioc->pdev = pdev;
-       pci_restore_state(pdev);
-       rc = mpt2sas_base_map_resources(ioc);
-       if (rc)
-               return PCI_ERS_RESULT_DISCONNECT;
-
-
-       rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-           FORCE_BIG_HAMMER);
-
-       printk(MPT2SAS_WARN_FMT "hard reset: %s\n", ioc->name,
-           (rc == 0) ? "success" : "failed");
-
-       if (!rc)
-               return PCI_ERS_RESULT_RECOVERED;
-       else
-               return PCI_ERS_RESULT_DISCONNECT;
-}
-
-/**
- * _scsih_pci_resume() - resume normal ops after PCI reset
- * @pdev: pointer to PCI device
- *
- * Called when the error recovery driver tells us that its
- * OK to resume normal operation. Use completion to allow
- * halted scsi ops to resume.
- */
-static void
-_scsih_pci_resume(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       printk(MPT2SAS_INFO_FMT "PCI error: resume callback!!\n", ioc->name);
-
-       pci_cleanup_aer_uncorrect_error_status(pdev);
-       mpt2sas_base_start_watchdog(ioc);
-       scsi_unblock_requests(ioc->shost);
-}
-
-/**
- * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
- * @pdev: pointer to PCI device
- */
-static pci_ers_result_t
-_scsih_pci_mmio_enabled(struct pci_dev *pdev)
-{
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-
-       printk(MPT2SAS_INFO_FMT "PCI error: mmio enabled callback!!\n",
-           ioc->name);
-
-       /* TODO - dump whatever for debugging purposes */
-
-       /* Request a slot reset. */
-       return PCI_ERS_RESULT_NEED_RESET;
-}
-
-static const struct pci_error_handlers _scsih_err_handler = {
-       .error_detected = _scsih_pci_error_detected,
-       .mmio_enabled = _scsih_pci_mmio_enabled,
-       .slot_reset =   _scsih_pci_slot_reset,
-       .resume =       _scsih_pci_resume,
-};
-
-static struct pci_driver scsih_driver = {
-       .name           = MPT2SAS_DRIVER_NAME,
-       .id_table       = scsih_pci_table,
-       .probe          = _scsih_probe,
-       .remove         = _scsih_remove,
-       .shutdown       = _scsih_shutdown,
-       .err_handler    = &_scsih_err_handler,
-#ifdef CONFIG_PM
-       .suspend        = _scsih_suspend,
-       .resume         = _scsih_resume,
-#endif
-};
-
-/* raid transport support */
-static struct raid_function_template mpt2sas_raid_functions = {
-       .cookie         = &scsih_driver_template,
-       .is_raid        = _scsih_is_raid,
-       .get_resync     = _scsih_get_resync,
-       .get_state      = _scsih_get_state,
-};
-
-/**
- * _scsih_init - main entry point for this driver.
- *
- * Returns 0 success, anything else error.
- */
-static int __init
-_scsih_init(void)
-{
-       int error;
-
-       mpt_ids = 0;
-       printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
-           MPT2SAS_DRIVER_VERSION);
-
-       mpt2sas_transport_template =
-           sas_attach_transport(&mpt2sas_transport_functions);
-       if (!mpt2sas_transport_template)
-               return -ENODEV;
-       /* raid transport support */
-       mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions);
-       if (!mpt2sas_raid_template) {
-               sas_release_transport(mpt2sas_transport_template);
-               return -ENODEV;
-       }
-
-       mpt2sas_base_initialize_callback_handler();
-
-        /* queuecommand callback hander */
-       scsi_io_cb_idx = mpt2sas_base_register_callback_handler(_scsih_io_done);
-
-       /* task management callback handler */
-       tm_cb_idx = mpt2sas_base_register_callback_handler(_scsih_tm_done);
-
-       /* base internal commands callback handler */
-       base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
-       port_enable_cb_idx = mpt2sas_base_register_callback_handler(
-               mpt2sas_port_enable_done);
-
-       /* transport internal commands callback handler */
-       transport_cb_idx = mpt2sas_base_register_callback_handler(
-           mpt2sas_transport_done);
-
-       /* scsih internal commands callback handler */
-       scsih_cb_idx = mpt2sas_base_register_callback_handler(_scsih_done);
-
-       /* configuration page API internal commands callback handler */
-       config_cb_idx = mpt2sas_base_register_callback_handler(
-           mpt2sas_config_done);
-
-       /* 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_tr_volume_cb_idx = mpt2sas_base_register_callback_handler(
-           _scsih_tm_volume_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);
-       if (error) {
-               /* raid transport support */
-               raid_class_release(mpt2sas_raid_template);
-               sas_release_transport(mpt2sas_transport_template);
-       }
-
-       return error;
-}
-
-/**
- * _scsih_exit - exit point for this driver (when it is a module).
- *
- * Returns 0 success, anything else error.
- */
-static void __exit
-_scsih_exit(void)
-{
-       printk(KERN_INFO "mpt2sas version %s unloading\n",
-           MPT2SAS_DRIVER_VERSION);
-
-       pci_unregister_driver(&scsih_driver);
-
-       mpt2sas_ctl_exit();
-
-       mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
-       mpt2sas_base_release_callback_handler(tm_cb_idx);
-       mpt2sas_base_release_callback_handler(base_cb_idx);
-       mpt2sas_base_release_callback_handler(port_enable_cb_idx);
-       mpt2sas_base_release_callback_handler(transport_cb_idx);
-       mpt2sas_base_release_callback_handler(scsih_cb_idx);
-       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_tr_volume_cb_idx);
-       mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx);
-
-       /* raid transport support */
-       raid_class_release(mpt2sas_raid_template);
-       sas_release_transport(mpt2sas_transport_template);
-
-}
-
-module_init(_scsih_init);
-module_exit(_scsih_exit);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
deleted file mode 100644 (file)
index af86800..0000000
+++ /dev/null
@@ -1,2173 +0,0 @@
-/*
- * SAS Transport Layer for MPT (Message Passing Technology) based controllers
- *
- * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
- * Copyright (C) 2007-2014  LSI Corporation
- * Copyright (C) 20013-2014 Avago Technologies
- *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * NO WARRANTY
- * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
- * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
- * solely responsible for determining the appropriateness of using and
- * distributing the Program and assumes all risks associated with its
- * exercise of rights under this Agreement, including but not limited to
- * the risks and costs of program errors, damage to or loss of data,
- * programs or equipment, and unavailability or interruption of operations.
-
- * DISCLAIMER OF LIABILITY
- * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
- * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
-
- * 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/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_transport_sas.h>
-#include <scsi/scsi_dbg.h>
-
-#include "mpt2sas_base.h"
-/**
- * _transport_sas_node_find_by_sas_address - sas node search
- * @ioc: per adapter object
- * @sas_address: sas address of expander or sas host
- * Context: Calling function should acquire ioc->sas_node_lock.
- *
- * Search for either hba phys or expander device based on handle, then returns
- * the sas_node object.
- */
-static struct _sas_node *
-_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
-    u64 sas_address)
-{
-       if (ioc->sas_hba.sas_address == sas_address)
-               return &ioc->sas_hba;
-       else
-               return mpt2sas_scsih_expander_find_by_sas_address(ioc,
-                   sas_address);
-}
-
-/**
- * _transport_convert_phy_link_rate -
- * @link_rate: link rate returned from mpt firmware
- *
- * Convert link_rate from mpi fusion into sas_transport form.
- */
-static enum sas_linkrate
-_transport_convert_phy_link_rate(u8 link_rate)
-{
-       enum sas_linkrate rc;
-
-       switch (link_rate) {
-       case MPI2_SAS_NEG_LINK_RATE_1_5:
-               rc = SAS_LINK_RATE_1_5_GBPS;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_3_0:
-               rc = SAS_LINK_RATE_3_0_GBPS;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_6_0:
-               rc = SAS_LINK_RATE_6_0_GBPS;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
-               rc = SAS_PHY_DISABLED;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
-               rc = SAS_LINK_RATE_FAILED;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
-               rc = SAS_SATA_PORT_SELECTOR;
-               break;
-       case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
-               rc = SAS_PHY_RESET_IN_PROGRESS;
-               break;
-       default:
-       case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
-       case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
-               rc = SAS_LINK_RATE_UNKNOWN;
-               break;
-       }
-       return rc;
-}
-
-/**
- * _transport_set_identify - set identify for phys and end devices
- * @ioc: per adapter object
- * @handle: device handle
- * @identify: sas identify info
- *
- * Populates sas identify info.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-    struct sas_identify *identify)
-{
-       Mpi2SasDevicePage0_t sas_device_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u32 device_info;
-       u32 ioc_status;
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               return -EFAULT;
-       }
-
-       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
-           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -ENXIO;
-       }
-
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
-                   "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
-                    __FILE__, __LINE__, __func__);
-               return -EIO;
-       }
-
-       memset(identify, 0, sizeof(struct sas_identify));
-       device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
-
-       /* sas_address */
-       identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-
-       /* phy number of the parent device this device is linked to */
-       identify->phy_identifier = sas_device_pg0.PhyNum;
-
-       /* device_type */
-       switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
-       case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
-               identify->device_type = SAS_PHY_UNUSED;
-               break;
-       case MPI2_SAS_DEVICE_INFO_END_DEVICE:
-               identify->device_type = SAS_END_DEVICE;
-               break;
-       case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
-               identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
-               break;
-       case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
-               identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
-               break;
-       }
-
-       /* initiator_port_protocols */
-       if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
-               identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
-               identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
-               identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
-               identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
-
-       /* target_port_protocols */
-       if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
-               identify->target_port_protocols |= SAS_PROTOCOL_SSP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
-               identify->target_port_protocols |= SAS_PROTOCOL_STP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
-               identify->target_port_protocols |= SAS_PROTOCOL_SMP;
-       if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
-               identify->target_port_protocols |= SAS_PROTOCOL_SATA;
-
-       return 0;
-}
-
-/**
- * mpt2sas_transport_done -  internal transport layer callback handler.
- * @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)
- *
- * Callback handler when sending internal generated transport cmds.
- * The callback index passed is `ioc->transport_cb_idx`
- *
- * Return 1 meaning mf should be freed from _base_interrupt
- *        0 means the mf is freed from this function.
- */
-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 1;
-       if (ioc->transport_cmds.smid != smid)
-               return 1;
-       ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
-       if (mpi_reply) {
-               memcpy(ioc->transport_cmds.reply, mpi_reply,
-                   mpi_reply->MsgLength*4);
-               ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
-       }
-       ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
-       complete(&ioc->transport_cmds.done);
-       return 1;
-}
-
-/* report manufacture request structure */
-struct rep_manu_request{
-       u8 smp_frame_type;
-       u8 function;
-       u8 reserved;
-       u8 request_length;
-};
-
-/* report manufacture reply structure */
-struct rep_manu_reply{
-       u8 smp_frame_type; /* 0x41 */
-       u8 function; /* 0x01 */
-       u8 function_result;
-       u8 response_length;
-       u16 expander_change_count;
-       u8 reserved0[2];
-       u8 sas_format;
-       u8 reserved2[3];
-       u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
-       u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
-       u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
-       u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
-       u16 component_id;
-       u8 component_revision_id;
-       u8 reserved3;
-       u8 vendor_specific[8];
-};
-
-/**
- * _transport_expander_report_manufacture - obtain SMP report_manufacture
- * @ioc: per adapter object
- * @sas_address: expander sas address
- * @edev: the sas_expander_device object
- *
- * Fills in the sas_expander_device object when SMP port is created.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
-    u64 sas_address, struct sas_expander_device *edev)
-{
-       Mpi2SmpPassthroughRequest_t *mpi_request;
-       Mpi2SmpPassthroughReply_t *mpi_reply;
-       struct rep_manu_reply *manufacture_reply;
-       struct rep_manu_request *manufacture_request;
-       int rc;
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       void *psge;
-       u32 sgl_flags;
-       u8 issue_reset = 0;
-       void *data_out = NULL;
-       dma_addr_t data_out_dma;
-       u32 sz;
-       u16 wait_state_count;
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               return -EFAULT;
-       }
-
-       mutex_lock(&ioc->transport_cmds.mutex);
-
-       if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-       ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       rc = 0;
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->transport_cmds.smid = smid;
-
-       sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
-       data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
-
-       if (!data_out) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                   __LINE__, __func__);
-               rc = -ENOMEM;
-               mpt2sas_base_free_smid(ioc, smid);
-               goto out;
-       }
-
-       manufacture_request = data_out;
-       manufacture_request->smp_frame_type = 0x40;
-       manufacture_request->function = 1;
-       manufacture_request->reserved = 0;
-       manufacture_request->request_length = 0;
-
-       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;
-       mpi_request->SASAddress = cpu_to_le64(sas_address);
-       mpi_request->RequestDataLength =
-           cpu_to_le16(sizeof(struct rep_manu_request));
-       psge = &mpi_request->SGL;
-
-       /* WRITE sgel first */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct rep_manu_request), data_out_dma);
-
-       /* incr sgel */
-       psge += ioc->sge_size;
-
-       /* READ sgel last */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-           MPI2_SGE_FLAGS_END_OF_LIST);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct rep_manu_reply), data_out_dma +
-           sizeof(struct rep_manu_request));
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
-           "send to sas_addr(0x%016llx)\n", ioc->name,
-           (unsigned long long)sas_address));
-       init_completion(&ioc->transport_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
-           10*HZ);
-
-       if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
-               if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
-           "complete\n", ioc->name));
-
-       if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-               u8 *tmp;
-
-               mpi_reply = ioc->transport_cmds.reply;
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "report_manufacture - reply data transfer size(%d)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
-               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
-                   sizeof(struct rep_manu_reply))
-                       goto out;
-
-               manufacture_reply = data_out + sizeof(struct rep_manu_request);
-               strncpy(edev->vendor_id, manufacture_reply->vendor_id,
-                    SAS_EXPANDER_VENDOR_ID_LEN);
-               strncpy(edev->product_id, manufacture_reply->product_id,
-                    SAS_EXPANDER_PRODUCT_ID_LEN);
-               strncpy(edev->product_rev, manufacture_reply->product_rev,
-                    SAS_EXPANDER_PRODUCT_REV_LEN);
-               edev->level = manufacture_reply->sas_format & 1;
-               if (edev->level) {
-                       strncpy(edev->component_vendor_id,
-                           manufacture_reply->component_vendor_id,
-                            SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
-                       tmp = (u8 *)&manufacture_reply->component_id;
-                       edev->component_id = tmp[0] << 8 | tmp[1];
-                       edev->component_revision_id =
-                           manufacture_reply->component_revision_id;
-               }
-       } else
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "report_manufacture - no reply\n", ioc->name));
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
- out:
-       ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
-       if (data_out)
-               pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
-       mutex_unlock(&ioc->transport_cmds.mutex);
-       return rc;
-}
-
-/**
- * _transport_delete_port - helper function to removing a port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- *
- * Returns nothing.
- */
-static void
-_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
-       struct _sas_port *mpt2sas_port)
-{
-       u64 sas_address = mpt2sas_port->remote_identify.sas_address;
-       enum sas_device_type device_type =
-           mpt2sas_port->remote_identify.device_type;
-
-       dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
-           "remove: sas_addr(0x%016llx)\n",
-           (unsigned long long) sas_address);
-
-       ioc->logging_level |= MPT_DEBUG_TRANSPORT;
-       if (device_type == SAS_END_DEVICE)
-               mpt2sas_device_remove_by_sas_address(ioc, sas_address);
-       else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
-           device_type == SAS_FANOUT_EXPANDER_DEVICE)
-               mpt2sas_expander_remove(ioc, sas_address);
-       ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
-}
-
-/**
- * _transport_delete_phy - helper function to removing single phy from port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
-       struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
-{
-       u64 sas_address = mpt2sas_port->remote_identify.sas_address;
-
-       dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
-           "remove: sas_addr(0x%016llx), phy(%d)\n",
-           (unsigned long long) sas_address, mpt2sas_phy->phy_id);
-
-       list_del(&mpt2sas_phy->port_siblings);
-       mpt2sas_port->num_phys--;
-       sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
-       mpt2sas_phy->phy_belongs_to_port = 0;
-}
-
-/**
- * _transport_add_phy - helper function to adding single phy to port
- * @ioc: per adapter object
- * @mpt2sas_port: mpt2sas per port object
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
-       struct _sas_phy *mpt2sas_phy)
-{
-       u64 sas_address = mpt2sas_port->remote_identify.sas_address;
-
-       dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
-           "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
-           sas_address, mpt2sas_phy->phy_id);
-
-       list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
-       mpt2sas_port->num_phys++;
-       sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
-       mpt2sas_phy->phy_belongs_to_port = 1;
-}
-
-/**
- * _transport_add_phy_to_an_existing_port - adding new phy to existing port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @mpt2sas_phy: mpt2sas per phy object
- * @sas_address: sas address of device/expander were phy needs to be added to
- *
- * Returns nothing.
- */
-static void
-_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
-struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
-{
-       struct _sas_port *mpt2sas_port;
-       struct _sas_phy *phy_srch;
-
-       if (mpt2sas_phy->phy_belongs_to_port == 1)
-               return;
-
-       list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
-           port_list) {
-               if (mpt2sas_port->remote_identify.sas_address !=
-                   sas_address)
-                       continue;
-               list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
-                   port_siblings) {
-                       if (phy_srch == mpt2sas_phy)
-                               return;
-               }
-               _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
-                       return;
-       }
-
-}
-
-/**
- * _transport_del_phy_from_an_existing_port - delete phy from existing port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @mpt2sas_phy: mpt2sas per phy object
- *
- * Returns nothing.
- */
-static void
-_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
-       struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
-{
-       struct _sas_port *mpt2sas_port, *next;
-       struct _sas_phy *phy_srch;
-
-       if (mpt2sas_phy->phy_belongs_to_port == 0)
-               return;
-
-       list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
-           port_list) {
-               list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
-                   port_siblings) {
-                       if (phy_srch != mpt2sas_phy)
-                               continue;
-                       if (mpt2sas_port->num_phys == 1)
-                               _transport_delete_port(ioc, mpt2sas_port);
-                       else
-                               _transport_delete_phy(ioc, mpt2sas_port,
-                                   mpt2sas_phy);
-                       return;
-               }
-       }
-}
-
-/**
- * _transport_sanity_check - sanity check when adding a new port
- * @ioc: per adapter object
- * @sas_node: sas node object (either expander or sas host)
- * @sas_address: sas address of device being added
- *
- * See the explanation above from _transport_delete_duplicate_port
- */
-static void
-_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
-     u64 sas_address)
-{
-       int i;
-
-       for (i = 0; i < sas_node->num_phys; i++) {
-               if (sas_node->phy[i].remote_identify.sas_address != sas_address)
-                       continue;
-               if (sas_node->phy[i].phy_belongs_to_port == 1)
-                       _transport_del_phy_from_an_existing_port(ioc, sas_node,
-                           &sas_node->phy[i]);
-       }
-}
-
-/**
- * mpt2sas_transport_port_add - insert port to the list
- * @ioc: per adapter object
- * @handle: handle of attached device
- * @sas_address: sas address of parent expander or sas host
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Adding new port object to the sas_node->sas_port_list.
- *
- * Returns mpt2sas_port.
- */
-struct _sas_port *
-mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
-    u64 sas_address)
-{
-       struct _sas_phy *mpt2sas_phy, *next;
-       struct _sas_port *mpt2sas_port;
-       unsigned long flags;
-       struct _sas_node *sas_node;
-       struct sas_rphy *rphy;
-       int i;
-       struct sas_port *port;
-
-       mpt2sas_port = kzalloc(sizeof(struct _sas_port),
-           GFP_KERNEL);
-       if (!mpt2sas_port) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return NULL;
-       }
-
-       INIT_LIST_HEAD(&mpt2sas_port->port_list);
-       INIT_LIST_HEAD(&mpt2sas_port->phy_list);
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       if (!sas_node) {
-               printk(MPT2SAS_ERR_FMT "%s: Could not find "
-                   "parent sas_address(0x%016llx)!\n", ioc->name,
-                   __func__, (unsigned long long)sas_address);
-               goto out_fail;
-       }
-
-       if ((_transport_set_identify(ioc, handle,
-           &mpt2sas_port->remote_identify))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out_fail;
-       }
-
-       if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out_fail;
-       }
-
-       _transport_sanity_check(ioc, sas_node,
-           mpt2sas_port->remote_identify.sas_address);
-
-       for (i = 0; i < sas_node->num_phys; i++) {
-               if (sas_node->phy[i].remote_identify.sas_address !=
-                   mpt2sas_port->remote_identify.sas_address)
-                       continue;
-               list_add_tail(&sas_node->phy[i].port_siblings,
-                   &mpt2sas_port->phy_list);
-               mpt2sas_port->num_phys++;
-       }
-
-       if (!mpt2sas_port->num_phys) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out_fail;
-       }
-
-       port = sas_port_alloc_num(sas_node->parent_dev);
-       if ((sas_port_add(port))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               goto out_fail;
-       }
-
-       list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
-           port_siblings) {
-               if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-                       dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
-                           ", sas_addr(0x%016llx), phy(%d)\n", handle,
-                           (unsigned long long)
-                           mpt2sas_port->remote_identify.sas_address,
-                           mpt2sas_phy->phy_id);
-               sas_port_add_phy(port, mpt2sas_phy->phy);
-               mpt2sas_phy->phy_belongs_to_port = 1;
-       }
-
-       mpt2sas_port->port = port;
-       if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
-               rphy = sas_end_device_alloc(port);
-       else
-               rphy = sas_expander_alloc(port,
-                   mpt2sas_port->remote_identify.device_type);
-
-       rphy->identify = mpt2sas_port->remote_identify;
-       if ((sas_rphy_add(rphy))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-       }
-       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-               dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
-                   "sas_addr(0x%016llx)\n", handle,
-                   (unsigned long long)
-                   mpt2sas_port->remote_identify.sas_address);
-       mpt2sas_port->rphy = rphy;
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       /* fill in report manufacture */
-       if (mpt2sas_port->remote_identify.device_type ==
-           MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
-           mpt2sas_port->remote_identify.device_type ==
-           MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
-               _transport_expander_report_manufacture(ioc,
-                   mpt2sas_port->remote_identify.sas_address,
-                   rphy_to_expander_device(rphy));
-
-       return mpt2sas_port;
-
- out_fail:
-       list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
-           port_siblings)
-               list_del(&mpt2sas_phy->port_siblings);
-       kfree(mpt2sas_port);
-       return NULL;
-}
-
-/**
- * mpt2sas_transport_port_remove - remove port from the list
- * @ioc: per adapter object
- * @sas_address: sas address of attached device
- * @sas_address_parent: sas address of parent expander or sas host
- * Context: This function will acquire ioc->sas_node_lock.
- *
- * Removing object and freeing associated memory from the
- * ioc->sas_port_list.
- *
- * Return nothing.
- */
-void
-mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
-    u64 sas_address_parent)
-{
-       int i;
-       unsigned long flags;
-       struct _sas_port *mpt2sas_port, *next;
-       struct _sas_node *sas_node;
-       u8 found = 0;
-       struct _sas_phy *mpt2sas_phy, *next_phy;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       sas_node = _transport_sas_node_find_by_sas_address(ioc,
-           sas_address_parent);
-       if (!sas_node) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return;
-       }
-       list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
-           port_list) {
-               if (mpt2sas_port->remote_identify.sas_address != sas_address)
-                       continue;
-               found = 1;
-               list_del(&mpt2sas_port->port_list);
-               goto out;
-       }
- out:
-       if (!found) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return;
-       }
-
-       for (i = 0; i < sas_node->num_phys; i++) {
-               if (sas_node->phy[i].remote_identify.sas_address == sas_address)
-                       memset(&sas_node->phy[i].remote_identify, 0 ,
-                           sizeof(struct sas_identify));
-       }
-
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-       list_for_each_entry_safe(mpt2sas_phy, next_phy,
-           &mpt2sas_port->phy_list, port_siblings) {
-               if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-                       dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
-                           "remove: sas_addr(0x%016llx), phy(%d)\n",
-                           (unsigned long long)
-                           mpt2sas_port->remote_identify.sas_address,
-                           mpt2sas_phy->phy_id);
-               mpt2sas_phy->phy_belongs_to_port = 0;
-               sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
-               list_del(&mpt2sas_phy->port_siblings);
-       }
-       sas_port_delete(mpt2sas_port->port);
-       kfree(mpt2sas_port);
-}
-
-/**
- * mpt2sas_transport_add_host_phy - report sas_host phy to transport
- * @ioc: per adapter object
- * @mpt2sas_phy: mpt2sas per phy object
- * @phy_pg0: sas phy page 0
- * @parent_dev: parent device class object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
-    *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
-{
-       struct sas_phy *phy;
-       int phy_index = mpt2sas_phy->phy_id;
-
-
-       INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
-       phy = sas_phy_alloc(parent_dev, phy_index);
-       if (!phy) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-       if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
-           &mpt2sas_phy->identify))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-       phy->identify = mpt2sas_phy->identify;
-       mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
-       if (mpt2sas_phy->attached_handle)
-               _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
-                   &mpt2sas_phy->remote_identify);
-       phy->identify.phy_identifier = mpt2sas_phy->phy_id;
-       phy->negotiated_linkrate = _transport_convert_phy_link_rate(
-           phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
-       phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
-           phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
-       phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
-           phy_pg0.HwLinkRate >> 4);
-       phy->minimum_linkrate = _transport_convert_phy_link_rate(
-           phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
-       phy->maximum_linkrate = _transport_convert_phy_link_rate(
-           phy_pg0.ProgrammedLinkRate >> 4);
-
-       if ((sas_phy_add(phy))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               sas_phy_free(phy);
-               return -1;
-       }
-       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-               dev_printk(KERN_INFO, &phy->dev,
-                   "add: handle(0x%04x), sas_addr(0x%016llx)\n"
-                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
-                   mpt2sas_phy->handle, (unsigned long long)
-                   mpt2sas_phy->identify.sas_address,
-                   mpt2sas_phy->attached_handle,
-                   (unsigned long long)
-                   mpt2sas_phy->remote_identify.sas_address);
-       mpt2sas_phy->phy = phy;
-       return 0;
-}
-
-
-/**
- * mpt2sas_transport_add_expander_phy - report expander phy to transport
- * @ioc: per adapter object
- * @mpt2sas_phy: mpt2sas per phy object
- * @expander_pg1: expander page 1
- * @parent_dev: parent device class object
- *
- * Returns 0 for success, non-zero for failure.
- */
-int
-mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
-    *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
-{
-       struct sas_phy *phy;
-       int phy_index = mpt2sas_phy->phy_id;
-
-       INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
-       phy = sas_phy_alloc(parent_dev, phy_index);
-       if (!phy) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-       if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
-           &mpt2sas_phy->identify))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -1;
-       }
-       phy->identify = mpt2sas_phy->identify;
-       mpt2sas_phy->attached_handle =
-           le16_to_cpu(expander_pg1.AttachedDevHandle);
-       if (mpt2sas_phy->attached_handle)
-               _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
-                   &mpt2sas_phy->remote_identify);
-       phy->identify.phy_identifier = mpt2sas_phy->phy_id;
-       phy->negotiated_linkrate = _transport_convert_phy_link_rate(
-           expander_pg1.NegotiatedLinkRate &
-           MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
-       phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
-           expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
-       phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
-           expander_pg1.HwLinkRate >> 4);
-       phy->minimum_linkrate = _transport_convert_phy_link_rate(
-           expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
-       phy->maximum_linkrate = _transport_convert_phy_link_rate(
-           expander_pg1.ProgrammedLinkRate >> 4);
-
-       if ((sas_phy_add(phy))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               sas_phy_free(phy);
-               return -1;
-       }
-       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-               dev_printk(KERN_INFO, &phy->dev,
-                   "add: handle(0x%04x), sas_addr(0x%016llx)\n"
-                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
-                   mpt2sas_phy->handle, (unsigned long long)
-                   mpt2sas_phy->identify.sas_address,
-                   mpt2sas_phy->attached_handle,
-                   (unsigned long long)
-                   mpt2sas_phy->remote_identify.sas_address);
-       mpt2sas_phy->phy = phy;
-       return 0;
-}
-
-/**
- * mpt2sas_transport_update_links - refreshing phy link changes
- * @ioc: per adapter object
- * @sas_address: sas address of parent expander or sas host
- * @handle: attached device handle
- * @phy_numberv: phy number
- * @link_rate: new link rate
- *
- * Returns nothing.
- */
-void
-mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
-     u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
-{
-       unsigned long flags;
-       struct _sas_node *sas_node;
-       struct _sas_phy *mpt2sas_phy;
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery)
-               return;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
-       if (!sas_node) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return;
-       }
-
-       mpt2sas_phy = &sas_node->phy[phy_number];
-       mpt2sas_phy->attached_handle = handle;
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-       if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
-               _transport_set_identify(ioc, handle,
-                   &mpt2sas_phy->remote_identify);
-               _transport_add_phy_to_an_existing_port(ioc, sas_node,
-                   mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
-       } else
-               memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
-                   sas_identify));
-
-       if (mpt2sas_phy->phy)
-               mpt2sas_phy->phy->negotiated_linkrate =
-                   _transport_convert_phy_link_rate(link_rate);
-
-       if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
-               dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
-                   "refresh: parent sas_addr(0x%016llx),\n"
-                   "\tlink_rate(0x%02x), phy(%d)\n"
-                   "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
-                   (unsigned long long)sas_address,
-                   link_rate, phy_number, handle, (unsigned long long)
-                   mpt2sas_phy->remote_identify.sas_address);
-}
-
-static inline void *
-phy_to_ioc(struct sas_phy *phy)
-{
-       struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
-       return shost_priv(shost);
-}
-
-static inline void *
-rphy_to_ioc(struct sas_rphy *rphy)
-{
-       struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
-       return shost_priv(shost);
-}
-
-
-/* report phy error log structure */
-struct phy_error_log_request{
-       u8 smp_frame_type; /* 0x40 */
-       u8 function; /* 0x11 */
-       u8 allocated_response_length;
-       u8 request_length; /* 02 */
-       u8 reserved_1[5];
-       u8 phy_identifier;
-       u8 reserved_2[2];
-};
-
-/* report phy error log reply structure */
-struct phy_error_log_reply{
-       u8 smp_frame_type; /* 0x41 */
-       u8 function; /* 0x11 */
-       u8 function_result;
-       u8 response_length;
-       __be16 expander_change_count;
-       u8 reserved_1[3];
-       u8 phy_identifier;
-       u8 reserved_2[2];
-       __be32 invalid_dword;
-       __be32 running_disparity_error;
-       __be32 loss_of_dword_sync;
-       __be32 phy_reset_problem;
-};
-
-/**
- * _transport_get_expander_phy_error_log - return expander counters
- * @ioc: per adapter object
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
-    struct sas_phy *phy)
-{
-       Mpi2SmpPassthroughRequest_t *mpi_request;
-       Mpi2SmpPassthroughReply_t *mpi_reply;
-       struct phy_error_log_request *phy_error_log_request;
-       struct phy_error_log_reply *phy_error_log_reply;
-       int rc;
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       void *psge;
-       u32 sgl_flags;
-       u8 issue_reset = 0;
-       void *data_out = NULL;
-       dma_addr_t data_out_dma;
-       u32 sz;
-       u16 wait_state_count;
-
-       if (ioc->shost_recovery || ioc->pci_error_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               return -EFAULT;
-       }
-
-       mutex_lock(&ioc->transport_cmds.mutex);
-
-       if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-       ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->transport_cmds.smid = smid;
-
-       sz = sizeof(struct phy_error_log_request) +
-           sizeof(struct phy_error_log_reply);
-       data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
-       if (!data_out) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                   __LINE__, __func__);
-               rc = -ENOMEM;
-               mpt2sas_base_free_smid(ioc, smid);
-               goto out;
-       }
-
-       rc = -EINVAL;
-       memset(data_out, 0, sz);
-       phy_error_log_request = data_out;
-       phy_error_log_request->smp_frame_type = 0x40;
-       phy_error_log_request->function = 0x11;
-       phy_error_log_request->request_length = 2;
-       phy_error_log_request->allocated_response_length = 0;
-       phy_error_log_request->phy_identifier = phy->number;
-
-       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;
-       mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
-       mpi_request->RequestDataLength =
-           cpu_to_le16(sizeof(struct phy_error_log_request));
-       psge = &mpi_request->SGL;
-
-       /* WRITE sgel first */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct phy_error_log_request), data_out_dma);
-
-       /* incr sgel */
-       psge += ioc->sge_size;
-
-       /* READ sgel last */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-           MPI2_SGE_FLAGS_END_OF_LIST);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct phy_error_log_reply), data_out_dma +
-           sizeof(struct phy_error_log_request));
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
-           "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
-           (unsigned long long)phy->identify.sas_address, phy->number));
-       init_completion(&ioc->transport_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
-           10*HZ);
-
-       if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
-               if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
-           "complete\n", ioc->name));
-
-       if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
-               mpi_reply = ioc->transport_cmds.reply;
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_error_log - reply data transfer size(%d)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
-               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
-                   sizeof(struct phy_error_log_reply))
-                       goto out;
-
-               phy_error_log_reply = data_out +
-                   sizeof(struct phy_error_log_request);
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_error_log - function_result(%d)\n",
-                   ioc->name, phy_error_log_reply->function_result));
-
-               phy->invalid_dword_count =
-                   be32_to_cpu(phy_error_log_reply->invalid_dword);
-               phy->running_disparity_error_count =
-                   be32_to_cpu(phy_error_log_reply->running_disparity_error);
-               phy->loss_of_dword_sync_count =
-                   be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
-               phy->phy_reset_problem_count =
-                   be32_to_cpu(phy_error_log_reply->phy_reset_problem);
-               rc = 0;
-       } else
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_error_log - no reply\n", ioc->name));
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
- out:
-       ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
-       if (data_out)
-               pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
-       mutex_unlock(&ioc->transport_cmds.mutex);
-       return rc;
-}
-
-/**
- * _transport_get_linkerrors - return phy counters for both hba and expanders
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_get_linkerrors(struct sas_phy *phy)
-{
-       struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
-       unsigned long flags;
-       Mpi2ConfigReply_t mpi_reply;
-       Mpi2SasPhyPage1_t phy_pg1;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       if (_transport_sas_node_find_by_sas_address(ioc,
-           phy->identify.sas_address) == NULL) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return -EINVAL;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
-               return _transport_get_expander_phy_error_log(ioc, phy);
-
-       /* get hba phy error logs */
-       if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
-                   phy->number))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -ENXIO;
-       }
-
-       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
-               printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
-                   "(0x%04x), loginfo(0x%08x)\n", ioc->name,
-                   phy->number, le16_to_cpu(mpi_reply.IOCStatus),
-                   le32_to_cpu(mpi_reply.IOCLogInfo));
-
-       phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
-       phy->running_disparity_error_count =
-           le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
-       phy->loss_of_dword_sync_count =
-           le32_to_cpu(phy_pg1.LossDwordSynchCount);
-       phy->phy_reset_problem_count =
-           le32_to_cpu(phy_pg1.PhyResetProblemCount);
-       return 0;
-}
-
-/**
- * _transport_get_enclosure_identifier -
- * @phy: The sas phy object
- *
- * Obtain the enclosure logical id for an expander.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
-{
-       struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
-       struct _sas_device *sas_device;
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-           rphy->identify.sas_address);
-       if (sas_device) {
-               *identifier = sas_device->enclosure_logical_id;
-               rc = 0;
-               sas_device_put(sas_device);
-       } else {
-               *identifier = 0;
-               rc = -ENXIO;
-       }
-
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       return rc;
-}
-
-/**
- * _transport_get_bay_identifier -
- * @phy: The sas phy object
- *
- * Returns the slot id for a device that resides inside an enclosure.
- */
-static int
-_transport_get_bay_identifier(struct sas_rphy *rphy)
-{
-       struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
-       struct _sas_device *sas_device;
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = __mpt2sas_get_sdev_by_addr(ioc,
-           rphy->identify.sas_address);
-       if (sas_device) {
-               rc = sas_device->slot;
-               sas_device_put(sas_device);
-       } else {
-               rc = -ENXIO;
-       }
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       return rc;
-}
-
-/* phy control request structure */
-struct phy_control_request{
-       u8 smp_frame_type; /* 0x40 */
-       u8 function; /* 0x91 */
-       u8 allocated_response_length;
-       u8 request_length; /* 0x09 */
-       u16 expander_change_count;
-       u8 reserved_1[3];
-       u8 phy_identifier;
-       u8 phy_operation;
-       u8 reserved_2[13];
-       u64 attached_device_name;
-       u8 programmed_min_physical_link_rate;
-       u8 programmed_max_physical_link_rate;
-       u8 reserved_3[6];
-};
-
-/* phy control reply structure */
-struct phy_control_reply{
-       u8 smp_frame_type; /* 0x41 */
-       u8 function; /* 0x11 */
-       u8 function_result;
-       u8 response_length;
-};
-
-#define SMP_PHY_CONTROL_LINK_RESET     (0x01)
-#define SMP_PHY_CONTROL_HARD_RESET     (0x02)
-#define SMP_PHY_CONTROL_DISABLE                (0x03)
-
-/**
- * _transport_expander_phy_control - expander phy control
- * @ioc: per adapter object
- * @phy: The sas phy object
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-static int
-_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
-    struct sas_phy *phy, u8 phy_operation)
-{
-       Mpi2SmpPassthroughRequest_t *mpi_request;
-       Mpi2SmpPassthroughReply_t *mpi_reply;
-       struct phy_control_request *phy_control_request;
-       struct phy_control_reply *phy_control_reply;
-       int rc;
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       void *psge;
-       u32 sgl_flags;
-       u8 issue_reset = 0;
-       void *data_out = NULL;
-       dma_addr_t data_out_dma;
-       u32 sz;
-       u16 wait_state_count;
-
-       if (ioc->shost_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               return -EFAULT;
-       }
-
-       mutex_lock(&ioc->transport_cmds.mutex);
-
-       if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-       ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto out;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->transport_cmds.smid = smid;
-
-       sz = sizeof(struct phy_control_request) +
-           sizeof(struct phy_control_reply);
-       data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
-       if (!data_out) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
-                   __LINE__, __func__);
-               rc = -ENOMEM;
-               mpt2sas_base_free_smid(ioc, smid);
-               goto out;
-       }
-
-       rc = -EINVAL;
-       memset(data_out, 0, sz);
-       phy_control_request = data_out;
-       phy_control_request->smp_frame_type = 0x40;
-       phy_control_request->function = 0x91;
-       phy_control_request->request_length = 9;
-       phy_control_request->allocated_response_length = 0;
-       phy_control_request->phy_identifier = phy->number;
-       phy_control_request->phy_operation = phy_operation;
-       phy_control_request->programmed_min_physical_link_rate =
-           phy->minimum_linkrate << 4;
-       phy_control_request->programmed_max_physical_link_rate =
-           phy->maximum_linkrate << 4;
-
-       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;
-       mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
-       mpi_request->RequestDataLength =
-           cpu_to_le16(sizeof(struct phy_error_log_request));
-       psge = &mpi_request->SGL;
-
-       /* WRITE sgel first */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct phy_control_request), data_out_dma);
-
-       /* incr sgel */
-       psge += ioc->sge_size;
-
-       /* READ sgel last */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-           MPI2_SGE_FLAGS_END_OF_LIST);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       ioc->base_add_sg_single(psge, sgl_flags |
-           sizeof(struct phy_control_reply), data_out_dma +
-           sizeof(struct phy_control_request));
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
-           "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
-           (unsigned long long)phy->identify.sas_address, phy->number,
-           phy_operation));
-
-       init_completion(&ioc->transport_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
-           10*HZ);
-
-       if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s: timeout\n",
-                   ioc->name, __func__);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
-               if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
-           "complete\n", ioc->name));
-
-       if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
-               mpi_reply = ioc->transport_cmds.reply;
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_control - reply data transfer size(%d)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
-
-               if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
-                   sizeof(struct phy_control_reply))
-                       goto out;
-
-               phy_control_reply = data_out +
-                   sizeof(struct phy_control_request);
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_control - function_result(%d)\n",
-                   ioc->name, phy_control_reply->function_result));
-
-               rc = 0;
-       } else
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "phy_control - no reply\n", ioc->name));
-
- issue_host_reset:
-       if (issue_reset)
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
- out:
-       ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
-       if (data_out)
-               pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
-
-       mutex_unlock(&ioc->transport_cmds.mutex);
-       return rc;
-}
-
-/**
- * _transport_phy_reset -
- * @phy: The sas phy object
- * @hard_reset:
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_reset(struct sas_phy *phy, int hard_reset)
-{
-       struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
-       Mpi2SasIoUnitControlReply_t mpi_reply;
-       Mpi2SasIoUnitControlRequest_t mpi_request;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       if (_transport_sas_node_find_by_sas_address(ioc,
-           phy->identify.sas_address) == NULL) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return -EINVAL;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       /* handle expander phys */
-       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
-               return _transport_expander_phy_control(ioc, phy,
-                   (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
-                   SMP_PHY_CONTROL_LINK_RESET);
-
-       /* handle hba phys */
-       memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
-       mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
-       mpi_request.Operation = hard_reset ?
-           MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
-       mpi_request.PhyNum = phy->number;
-
-       if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               return -ENXIO;
-       }
-
-       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
-               printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
-                   "(0x%04x), loginfo(0x%08x)\n", ioc->name,
-                   phy->number, le16_to_cpu(mpi_reply.IOCStatus),
-                   le32_to_cpu(mpi_reply.IOCLogInfo));
-
-       return 0;
-}
-
-/**
- * _transport_phy_enable - enable/disable phys
- * @phy: The sas phy object
- * @enable: enable phy when true
- *
- * Only support sas_host direct attached phys.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_enable(struct sas_phy *phy, int enable)
-{
-       struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
-       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
-       Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 ioc_status;
-       u16 sz;
-       int rc = 0;
-       unsigned long flags;
-       int i, discovery_active;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       if (_transport_sas_node_find_by_sas_address(ioc,
-           phy->identify.sas_address) == NULL) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return -EINVAL;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       /* handle expander phys */
-       if (phy->identify.sas_address != ioc->sas_hba.sas_address)
-               return _transport_expander_phy_control(ioc, phy,
-                   (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
-                   SMP_PHY_CONTROL_DISABLE);
-
-       /* handle hba phys */
-
-       /* read sas_iounit page 0 */
-       sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
-           sizeof(Mpi2SasIOUnit0PhyData_t));
-       sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg0) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENOMEM;
-               goto out;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
-           sas_iounit_pg0, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENXIO;
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -EIO;
-               goto out;
-       }
-
-       /* unable to enable/disable phys when when discovery is active */
-       for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
-               if (sas_iounit_pg0->PhyData[i].PortFlags &
-                   MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
-                       printk(MPT2SAS_ERR_FMT "discovery is active on "
-                           "port = %d, phy = %d: unable to enable/disable "
-                           "phys, try again later!\n", ioc->name,
-                           sas_iounit_pg0->PhyData[i].Port, i);
-                       discovery_active = 1;
-               }
-       }
-
-       if (discovery_active) {
-               rc = -EAGAIN;
-               goto out;
-       }
-
-       /* read sas_iounit page 1 */
-       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
-           sizeof(Mpi2SasIOUnit1PhyData_t));
-       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg1) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENOMEM;
-               goto out;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
-           sas_iounit_pg1, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENXIO;
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -EIO;
-               goto out;
-       }
-       /* copy Port/PortFlags/PhyFlags from page 0 */
-       for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
-               sas_iounit_pg1->PhyData[i].Port =
-                   sas_iounit_pg0->PhyData[i].Port;
-               sas_iounit_pg1->PhyData[i].PortFlags =
-                   (sas_iounit_pg0->PhyData[i].PortFlags &
-                   MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
-               sas_iounit_pg1->PhyData[i].PhyFlags =
-                   (sas_iounit_pg0->PhyData[i].PhyFlags &
-                   (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
-                   MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
-       }
-       if (enable)
-               sas_iounit_pg1->PhyData[phy->number].PhyFlags
-                   &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
-       else
-               sas_iounit_pg1->PhyData[phy->number].PhyFlags
-                   |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
-
-       mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
-
-       /* link reset */
-       if (enable)
-               _transport_phy_reset(phy, 0);
-
- out:
-       kfree(sas_iounit_pg1);
-       kfree(sas_iounit_pg0);
-       return rc;
-}
-
-/**
- * _transport_phy_speed - set phy min/max link rates
- * @phy: The sas phy object
- * @rates: rates defined in sas_phy_linkrates
- *
- * Only support sas_host direct attached phys.
- * Returns 0 for success, non-zero for failure.
- */
-static int
-_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
-{
-       struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
-       Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
-       Mpi2SasPhyPage0_t phy_pg0;
-       Mpi2ConfigReply_t mpi_reply;
-       u16 ioc_status;
-       u16 sz;
-       int i;
-       int rc = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioc->sas_node_lock, flags);
-       if (_transport_sas_node_find_by_sas_address(ioc,
-           phy->identify.sas_address) == NULL) {
-               spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-               return -EINVAL;
-       }
-       spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
-
-       if (!rates->minimum_linkrate)
-               rates->minimum_linkrate = phy->minimum_linkrate;
-       else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
-               rates->minimum_linkrate = phy->minimum_linkrate_hw;
-
-       if (!rates->maximum_linkrate)
-               rates->maximum_linkrate = phy->maximum_linkrate;
-       else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
-               rates->maximum_linkrate = phy->maximum_linkrate_hw;
-
-       /* handle expander phys */
-       if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
-               phy->minimum_linkrate = rates->minimum_linkrate;
-               phy->maximum_linkrate = rates->maximum_linkrate;
-               return _transport_expander_phy_control(ioc, phy,
-                   SMP_PHY_CONTROL_LINK_RESET);
-       }
-
-       /* handle hba phys */
-
-       /* sas_iounit page 1 */
-       sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
-           sizeof(Mpi2SasIOUnit1PhyData_t));
-       sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
-       if (!sas_iounit_pg1) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENOMEM;
-               goto out;
-       }
-       if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
-           sas_iounit_pg1, sz))) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENXIO;
-               goto out;
-       }
-       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
-           MPI2_IOCSTATUS_MASK;
-       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -EIO;
-               goto out;
-       }
-
-       for (i = 0; i < ioc->sas_hba.num_phys; i++) {
-               if (phy->number != i) {
-                       sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
-                           (ioc->sas_hba.phy[i].phy->minimum_linkrate +
-                           (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
-               } else {
-                       sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
-                           (rates->minimum_linkrate +
-                           (rates->maximum_linkrate << 4));
-               }
-       }
-
-       if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
-           sz)) {
-               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
-                   ioc->name, __FILE__, __LINE__, __func__);
-               rc = -ENXIO;
-               goto out;
-       }
-
-       /* link reset */
-       _transport_phy_reset(phy, 0);
-
-       /* read phy page 0, then update the rates in the sas transport phy */
-       if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
-           phy->number)) {
-               phy->minimum_linkrate = _transport_convert_phy_link_rate(
-                   phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
-               phy->maximum_linkrate = _transport_convert_phy_link_rate(
-                   phy_pg0.ProgrammedLinkRate >> 4);
-               phy->negotiated_linkrate = _transport_convert_phy_link_rate(
-                   phy_pg0.NegotiatedLinkRate &
-                   MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
-       }
-
- out:
-       kfree(sas_iounit_pg1);
-       return rc;
-}
-
-
-/**
- * _transport_smp_handler - transport portal for smp passthru
- * @shost: shost object
- * @rphy: sas transport rphy object
- * @req:
- *
- * This used primarily for smp_utils.
- * Example:
- *           smp_rep_general /sys/class/bsg/expander-5:0
- */
-static int
-_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
-    struct request *req)
-{
-       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
-       Mpi2SmpPassthroughRequest_t *mpi_request;
-       Mpi2SmpPassthroughReply_t *mpi_reply;
-       int rc;
-       u16 smid;
-       u32 ioc_state;
-       unsigned long timeleft;
-       void *psge;
-       u32 sgl_flags;
-       u8 issue_reset = 0;
-       dma_addr_t dma_addr_in = 0;
-       dma_addr_t dma_addr_out = 0;
-       dma_addr_t pci_dma_in = 0;
-       dma_addr_t pci_dma_out = 0;
-       void *pci_addr_in = NULL;
-       void *pci_addr_out = NULL;
-       u16 wait_state_count;
-       struct request *rsp = req->next_rq;
-       struct bio_vec bvec;
-       struct bvec_iter iter;
-
-       if (!rsp) {
-               printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
-                   "missing\n", ioc->name, __func__);
-               return -EINVAL;
-       }
-       if (ioc->shost_recovery || ioc->pci_error_recovery) {
-               printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
-                   __func__, ioc->name);
-               return -EFAULT;
-       }
-
-       rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
-       if (rc)
-               return rc;
-
-       if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
-                   __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-       ioc->transport_cmds.status = MPT2_CMD_PENDING;
-
-       /* Check if the request is split across multiple segments */
-       if (bio_multiple_segments(req->bio)) {
-               u32 offset = 0;
-
-               /* Allocate memory and copy the request */
-               pci_addr_out = pci_alloc_consistent(ioc->pdev,
-                   blk_rq_bytes(req), &pci_dma_out);
-               if (!pci_addr_out) {
-                       printk(MPT2SAS_INFO_FMT "%s(): PCI Addr out = NULL\n",
-                           ioc->name, __func__);
-                       rc = -ENOMEM;
-                       goto out;
-               }
-
-               bio_for_each_segment(bvec, req->bio, iter) {
-                       memcpy(pci_addr_out + offset,
-                           page_address(bvec.bv_page) + bvec.bv_offset,
-                           bvec.bv_len);
-                       offset += bvec.bv_len;
-               }
-       } else {
-               dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
-                   blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
-               if (!dma_addr_out) {
-                       printk(MPT2SAS_INFO_FMT "%s(): DMA Addr out = NULL\n",
-                           ioc->name, __func__);
-                       rc = -ENOMEM;
-                       goto free_pci;
-               }
-       }
-
-       /* Check if the response needs to be populated across
-        * multiple segments */
-       if (bio_multiple_segments(rsp->bio)) {
-               pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
-                   &pci_dma_in);
-               if (!pci_addr_in) {
-                       printk(MPT2SAS_INFO_FMT "%s(): PCI Addr in = NULL\n",
-                           ioc->name, __func__);
-                       rc = -ENOMEM;
-                       goto unmap;
-               }
-       } else {
-               dma_addr_in =  pci_map_single(ioc->pdev, bio_data(rsp->bio),
-                   blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
-               if (!dma_addr_in) {
-                       printk(MPT2SAS_INFO_FMT "%s(): DMA Addr in = NULL\n",
-                           ioc->name, __func__);
-                       rc = -ENOMEM;
-                       goto unmap;
-               }
-       }
-
-       wait_state_count = 0;
-       ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-       while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               if (wait_state_count++ == 10) {
-                       printk(MPT2SAS_ERR_FMT
-                           "%s: failed due to ioc not operational\n",
-                           ioc->name, __func__);
-                       rc = -EFAULT;
-                       goto unmap;
-               }
-               ssleep(1);
-               ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
-               printk(MPT2SAS_INFO_FMT "%s: waiting for "
-                   "operational state(count=%d)\n", ioc->name,
-                   __func__, wait_state_count);
-       }
-       if (wait_state_count)
-               printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
-                   ioc->name, __func__);
-
-       smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto unmap;
-       }
-
-       rc = 0;
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->transport_cmds.smid = smid;
-
-       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;
-       mpi_request->SASAddress = (rphy) ?
-           cpu_to_le64(rphy->identify.sas_address) :
-           cpu_to_le64(ioc->sas_hba.sas_address);
-       mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
-       psge = &mpi_request->SGL;
-
-       /* WRITE sgel first */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       if (bio_multiple_segments(req->bio)) {
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   (blk_rq_bytes(req) - 4), pci_dma_out);
-       } else {
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   (blk_rq_bytes(req) - 4), dma_addr_out);
-       }
-
-       /* incr sgel */
-       psge += ioc->sge_size;
-
-       /* READ sgel last */
-       sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
-           MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
-           MPI2_SGE_FLAGS_END_OF_LIST);
-       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       if (bio_multiple_segments(rsp->bio)) {
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   (blk_rq_bytes(rsp) + 4), pci_dma_in);
-       } else {
-               ioc->base_add_sg_single(psge, sgl_flags |
-                   (blk_rq_bytes(rsp) + 4), dma_addr_in);
-       }
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
-           "sending smp request\n", ioc->name, __func__));
-
-       init_completion(&ioc->transport_cmds.done);
-       mpt2sas_base_put_smid_default(ioc, smid);
-       timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
-           10*HZ);
-
-       if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
-               printk(MPT2SAS_ERR_FMT "%s : timeout\n",
-                   __func__, ioc->name);
-               _debug_dump_mf(mpi_request,
-                   sizeof(Mpi2SmpPassthroughRequest_t)/4);
-               if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
-       }
-
-       dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
-           "complete\n", ioc->name, __func__));
-
-       if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
-
-               mpi_reply = ioc->transport_cmds.reply;
-
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "%s - reply data transfer size(%d)\n",
-                   ioc->name, __func__,
-                   le16_to_cpu(mpi_reply->ResponseDataLength)));
-
-               memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
-               req->sense_len = sizeof(*mpi_reply);
-               req->resid_len = 0;
-               rsp->resid_len -=
-                   le16_to_cpu(mpi_reply->ResponseDataLength);
-               /* check if the resp needs to be copied from the allocated
-                * pci mem */
-               if (bio_multiple_segments(rsp->bio)) {
-                       u32 offset = 0;
-                       u32 bytes_to_copy =
-                           le16_to_cpu(mpi_reply->ResponseDataLength);
-                       bio_for_each_segment(bvec, rsp->bio, iter) {
-                               if (bytes_to_copy <= bvec.bv_len) {
-                                       memcpy(page_address(bvec.bv_page) +
-                                           bvec.bv_offset, pci_addr_in +
-                                           offset, bytes_to_copy);
-                                       break;
-                               } else {
-                                       memcpy(page_address(bvec.bv_page) +
-                                           bvec.bv_offset, pci_addr_in +
-                                           offset, bvec.bv_len);
-                                       bytes_to_copy -= bvec.bv_len;
-                               }
-                               offset += bvec.bv_len;
-                       }
-               }
-       } else {
-               dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "%s - no reply\n", ioc->name, __func__));
-               rc = -ENXIO;
-       }
-
- issue_host_reset:
-       if (issue_reset) {
-               mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
-                   FORCE_BIG_HAMMER);
-               rc = -ETIMEDOUT;
-       }
-
- unmap:
-       if (dma_addr_out)
-               pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
-                   PCI_DMA_BIDIRECTIONAL);
-       if (dma_addr_in)
-               pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
-                   PCI_DMA_BIDIRECTIONAL);
-
- free_pci:
-       if (pci_addr_out)
-               pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
-                   pci_dma_out);
-
-       if (pci_addr_in)
-               pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
-                   pci_dma_in);
-
- out:
-       ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
-       mutex_unlock(&ioc->transport_cmds.mutex);
-       return rc;
-}
-
-struct sas_function_template mpt2sas_transport_functions = {
-       .get_linkerrors         = _transport_get_linkerrors,
-       .get_enclosure_identifier = _transport_get_enclosure_identifier,
-       .get_bay_identifier     = _transport_get_bay_identifier,
-       .phy_reset              = _transport_phy_reset,
-       .phy_enable             = _transport_phy_enable,
-       .set_phy_speed          = _transport_phy_speed,
-       .smp_handler            = _transport_smp_handler,
-};
-
-struct scsi_transport_template *mpt2sas_transport_template;
index 4d235dd741bf97499d74a38820f4c85fa2031358..29061467cc174e118848dd44244ff28bb198deb3 100644 (file)
 # USA.
 
 config SCSI_MPT3SAS
-       tristate "LSI MPT Fusion SAS 3.0 Device Driver"
+       tristate "LSI MPT Fusion SAS 3.0 & SAS 2.0 Device Driver"
        depends on PCI && SCSI
        select SCSI_SAS_ATTRS
        select RAID_ATTRS
        ---help---
        This driver supports PCI-Express SAS 12Gb/s Host Adapters.
 
-config SCSI_MPT3SAS_MAX_SGE
-       int "LSI MPT Fusion Max number of SG Entries (16 - 256)"
+config SCSI_MPT2SAS_MAX_SGE
+       int "LSI MPT Fusion SAS 2.0 Max number of SG Entries (16 - 256)"
        depends on PCI && SCSI && SCSI_MPT3SAS
        default "128"
        range 16 256
@@ -60,8 +60,14 @@ config SCSI_MPT3SAS_MAX_SGE
        can be 256. However, it may decreased down to 16.  Decreasing this
        parameter will reduce memory requirements on a per controller instance.
 
-config SCSI_MPT3SAS_LOGGING
-       bool "LSI MPT Fusion logging facility"
+config SCSI_MPT3SAS_MAX_SGE
+       int "LSI MPT Fusion SAS 3.0 Max number of SG Entries (16 - 256)"
        depends on PCI && SCSI && SCSI_MPT3SAS
+       default "128"
+       range 16 256
        ---help---
-       This turns on a logging facility.
+       This option allows you to specify the maximum number of scatter-
+       gather entries per I/O. The driver default is 128, which matches
+       MAX_PHYS_SEGMENTS in most kernels.  However in SuSE kernels this
+       can be 256. However, it may decreased down to 16.  Decreasing this
+       parameter will reduce memory requirements on a per controller instance.
index efb0c4c2e31000fd6f8e96777570c0d1086d1dae..b7643f596c1e67ab67e0a954ab2250577de637d8 100644 (file)
@@ -5,4 +5,5 @@ mpt3sas-y +=  mpt3sas_base.o     \
                mpt3sas_scsih.o      \
                mpt3sas_transport.o     \
                mpt3sas_ctl.o   \
-               mpt3sas_trigger_diag.o
+               mpt3sas_trigger_diag.o \
+               mpt3sas_warpdrive.o
index d4f1dcdb8361937c8b0cb75491ec45e1b4981188..11393ebf1a68ef8f14a38d58f1321d7783a84d72 100644 (file)
@@ -108,9 +108,12 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp)
        if (ret)
                return ret;
 
+       /* global ioc spinlock to protect controller list on list operations */
        pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug);
+       spin_lock(&gioc_lock);
        list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
                ioc->fwfault_debug = mpt3sas_fwfault_debug;
+       spin_unlock(&gioc_lock);
        return 0;
 }
 module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
@@ -157,7 +160,7 @@ _base_fault_reset_work(struct work_struct *work)
 
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->shost_recovery)
+       if (ioc->shost_recovery || ioc->pci_error_recovery)
                goto rearm_timer;
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
@@ -166,6 +169,20 @@ _base_fault_reset_work(struct work_struct *work)
                pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n",
                    ioc->name);
 
+               /* It may be possible that EEH recovery can resolve some of
+                * pci bus failure issues rather removing the dead ioc function
+                * by considering controller is in a non-operational state. So
+                * here priority is given to the EEH recovery. If it doesn't
+                * not resolve this issue, mpt3sas driver will consider this
+                * controller to non-operational state and remove the dead ioc
+                * function.
+                */
+               if (ioc->non_operational_loop++ < 5) {
+                       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock,
+                                                        flags);
+                       goto rearm_timer;
+               }
+
                /*
                 * Call _scsih_flush_pending_cmds callback so that we flush all
                 * pending commands back to OS. This call is required to aovid
@@ -181,7 +198,7 @@ _base_fault_reset_work(struct work_struct *work)
                ioc->remove_host = 1;
                /*Remove the Dead Host */
                p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc,
-                   "mpt3sas_dead_ioc_%d", ioc->id);
+                   "%s_dead_ioc_%d", ioc->driver_name, ioc->id);
                if (IS_ERR(p))
                        pr_err(MPT3SAS_FMT
                        "%s: Running mpt3sas_dead_ioc thread failed !!!!\n",
@@ -193,6 +210,8 @@ _base_fault_reset_work(struct work_struct *work)
                return; /* don't rearm timer */
        }
 
+       ioc->non_operational_loop = 0;
+
        if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
                rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
                    FORCE_BIG_HAMMER);
@@ -235,7 +254,8 @@ mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc)
 
        INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
        snprintf(ioc->fault_reset_work_q_name,
-           sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+           sizeof(ioc->fault_reset_work_q_name), "poll_%s%d_status",
+           ioc->driver_name, ioc->id);
        ioc->fault_reset_work_q =
                create_singlethread_workqueue(ioc->fault_reset_work_q_name);
        if (!ioc->fault_reset_work_q) {
@@ -324,7 +344,6 @@ mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc)
                panic("panic in %s\n", __func__);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _base_sas_ioc_info - verbose translation of the ioc status
  * @ioc: per adapter object
@@ -578,7 +597,8 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
                desc = "Device Status Change";
                break;
        case MPI2_EVENT_IR_OPERATION_STATUS:
-               desc = "IR Operation Status";
+               if (!ioc->hide_ir_msg)
+                       desc = "IR Operation Status";
                break;
        case MPI2_EVENT_SAS_DISCOVERY:
        {
@@ -609,16 +629,20 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
                desc = "SAS Enclosure Device Status Change";
                break;
        case MPI2_EVENT_IR_VOLUME:
-               desc = "IR Volume";
+               if (!ioc->hide_ir_msg)
+                       desc = "IR Volume";
                break;
        case MPI2_EVENT_IR_PHYSICAL_DISK:
-               desc = "IR Physical Disk";
+               if (!ioc->hide_ir_msg)
+                       desc = "IR Physical Disk";
                break;
        case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
-               desc = "IR Configuration Change List";
+               if (!ioc->hide_ir_msg)
+                       desc = "IR Configuration Change List";
                break;
        case MPI2_EVENT_LOG_ENTRY_ADDED:
-               desc = "Log Entry Added";
+               if (!ioc->hide_ir_msg)
+                       desc = "Log Entry Added";
                break;
        case MPI2_EVENT_TEMP_THRESHOLD:
                desc = "Temperature Threshold";
@@ -630,7 +654,6 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
 
        pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc);
 }
-#endif
 
 /**
  * _base_sas_log_info - verbose translation of firmware log info
@@ -675,7 +698,10 @@ _base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info)
                originator_str = "PL";
                break;
        case 2:
-               originator_str = "IR";
+               if (!ioc->hide_ir_msg)
+                       originator_str = "IR";
+               else
+                       originator_str = "WarpDrive";
                break;
        }
 
@@ -710,13 +736,13 @@ _base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
                return;
        }
        ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
        if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
            (ioc->logging_level & MPT_DEBUG_REPLY)) {
                _base_sas_ioc_info(ioc , mpi_reply,
                   mpt3sas_base_get_msg_frame(ioc, smid));
        }
-#endif
+
        if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
                loginfo = le32_to_cpu(mpi_reply->IOCLogInfo);
                _base_sas_log_info(ioc, loginfo);
@@ -783,9 +809,9 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
                return 1;
        if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
                return 1;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
        _base_display_event_data(ioc, mpi_reply);
-#endif
+
        if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
                goto out;
        smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
@@ -1009,6 +1035,12 @@ _base_interrupt(int irq, void *bus_id)
        }
 
        wmb();
+       if (ioc->is_warpdrive) {
+               writel(reply_q->reply_post_host_index,
+               ioc->reply_post_host_index[msix_index]);
+               atomic_dec(&reply_q->busy);
+               return IRQ_HANDLED;
+       }
 
        /* Update Reply Post Host Index.
         * For those HBA's which support combined reply queue feature
@@ -1319,6 +1351,149 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
        _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
 }
 
+/**
+ * _base_build_sg_scmd - main sg creation routine
+ * @ioc: per adapter object
+ * @scmd: scsi command
+ * @smid: system request message index
+ * Context: none.
+ *
+ * The main routine that builds scatter gather table from a given
+ * scsi request sent via the .queuecommand main handler.
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
+               struct scsi_cmnd *scmd, u16 smid)
+{
+       Mpi2SCSIIORequest_t *mpi_request;
+       dma_addr_t chain_dma;
+       struct scatterlist *sg_scmd;
+       void *sg_local, *chain;
+       u32 chain_offset;
+       u32 chain_length;
+       u32 chain_flags;
+       int sges_left;
+       u32 sges_in_segment;
+       u32 sgl_flags;
+       u32 sgl_flags_last_element;
+       u32 sgl_flags_end_buffer;
+       struct chain_tracker *chain_req;
+
+       mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+       /* init scatter gather flags */
+       sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
+       if (scmd->sc_data_direction == DMA_TO_DEVICE)
+               sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
+       sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
+           << MPI2_SGE_FLAGS_SHIFT;
+       sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
+           MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
+           << MPI2_SGE_FLAGS_SHIFT;
+       sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+
+       sg_scmd = scsi_sglist(scmd);
+       sges_left = scsi_dma_map(scmd);
+       if (sges_left < 0) {
+               sdev_printk(KERN_ERR, scmd->device,
+                "pci_map_sg failed: request for %d bytes!\n",
+                scsi_bufflen(scmd));
+               return -ENOMEM;
+       }
+
+       sg_local = &mpi_request->SGL;
+       sges_in_segment = ioc->max_sges_in_main_message;
+       if (sges_left <= sges_in_segment)
+               goto fill_in_last_segment;
+
+       mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
+           (sges_in_segment * ioc->sge_size))/4;
+
+       /* fill in main message segment when there is a chain following */
+       while (sges_in_segment) {
+               if (sges_in_segment == 1)
+                       ioc->base_add_sg_single(sg_local,
+                           sgl_flags_last_element | sg_dma_len(sg_scmd),
+                           sg_dma_address(sg_scmd));
+               else
+                       ioc->base_add_sg_single(sg_local, sgl_flags |
+                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+               sg_scmd = sg_next(sg_scmd);
+               sg_local += ioc->sge_size;
+               sges_left--;
+               sges_in_segment--;
+       }
+
+       /* initializing the chain flags and pointers */
+       chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
+       chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+       if (!chain_req)
+               return -1;
+       chain = chain_req->chain_buffer;
+       chain_dma = chain_req->chain_buffer_dma;
+       do {
+               sges_in_segment = (sges_left <=
+                   ioc->max_sges_in_chain_message) ? sges_left :
+                   ioc->max_sges_in_chain_message;
+               chain_offset = (sges_left == sges_in_segment) ?
+                   0 : (sges_in_segment * ioc->sge_size)/4;
+               chain_length = sges_in_segment * ioc->sge_size;
+               if (chain_offset) {
+                       chain_offset = chain_offset <<
+                           MPI2_SGE_CHAIN_OFFSET_SHIFT;
+                       chain_length += ioc->sge_size;
+               }
+               ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
+                   chain_length, chain_dma);
+               sg_local = chain;
+               if (!chain_offset)
+                       goto fill_in_last_segment;
+
+               /* fill in chain segments */
+               while (sges_in_segment) {
+                       if (sges_in_segment == 1)
+                               ioc->base_add_sg_single(sg_local,
+                                   sgl_flags_last_element |
+                                   sg_dma_len(sg_scmd),
+                                   sg_dma_address(sg_scmd));
+                       else
+                               ioc->base_add_sg_single(sg_local, sgl_flags |
+                                   sg_dma_len(sg_scmd),
+                                   sg_dma_address(sg_scmd));
+                       sg_scmd = sg_next(sg_scmd);
+                       sg_local += ioc->sge_size;
+                       sges_left--;
+                       sges_in_segment--;
+               }
+
+               chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+               if (!chain_req)
+                       return -1;
+               chain = chain_req->chain_buffer;
+               chain_dma = chain_req->chain_buffer_dma;
+       } while (1);
+
+
+ fill_in_last_segment:
+
+       /* fill the last segment */
+       while (sges_left) {
+               if (sges_left == 1)
+                       ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
+                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+               else
+                       ioc->base_add_sg_single(sg_local, sgl_flags |
+                           sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+               sg_scmd = sg_next(sg_scmd);
+               sg_local += ioc->sge_size;
+               sges_left--;
+       }
+
+       return 0;
+}
+
 /**
  * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format
  * @ioc: per adapter object
@@ -1571,6 +1746,14 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
        int base;
        u16 message_control;
 
+       /* Check whether controller SAS2008 B0 controller,
+        * if it is SAS2008 B0 controller use IO-APIC instead of MSIX
+        */
+       if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
+           ioc->pdev->revision == SAS2_PCI_DEVICE_B0_REVISION) {
+               return -EINVAL;
+       }
+
        base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
        if (!base) {
                dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n",
@@ -1579,9 +1762,19 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc)
        }
 
        /* get msix vector count */
-
-       pci_read_config_word(ioc->pdev, base + 2, &message_control);
-       ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+       /* NUMA_IO not supported for older controllers */
+       if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 ||
+           ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2)
+               ioc->msix_vector_count = 1;
+       else {
+               pci_read_config_word(ioc->pdev, base + 2, &message_control);
+               ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+       }
        dinitprintk(ioc, pr_info(MPT3SAS_FMT
                "msix is supported, vector_count(%d)\n",
                ioc->name, ioc->msix_vector_count));
@@ -1643,10 +1836,10 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
        atomic_set(&reply_q->busy, 0);
        if (ioc->msix_enable)
                snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d",
-                   MPT3SAS_DRIVER_NAME, ioc->id, index);
+                   ioc->driver_name, ioc->id, index);
        else
                snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d",
-                   MPT3SAS_DRIVER_NAME, ioc->id);
+                   ioc->driver_name, ioc->id);
        r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name,
            reply_q);
        if (r) {
@@ -1872,7 +2065,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
 
 
        if (pci_request_selected_regions(pdev, ioc->bars,
-           MPT3SAS_DRIVER_NAME)) {
+           ioc->driver_name)) {
                pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n",
                        ioc->name);
                ioc->bars = 0;
@@ -2158,6 +2351,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
                }
                ioc->scsi_lookup[i].cb_idx = 0xFF;
                ioc->scsi_lookup[i].scmd = NULL;
+               ioc->scsi_lookup[i].direct_io = 0;
                list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list);
                spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
@@ -2318,143 +2512,261 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 }
 
 /**
- * _base_display_intel_branding - Display branding string
+ * _base_display_OEMs_branding - Display branding string
  * @ioc: per adapter object
  *
  * Return nothing.
  */
 static void
-_base_display_intel_branding(struct MPT3SAS_ADAPTER *ioc)
+_base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc)
 {
        if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
                return;
 
-       switch (ioc->pdev->device) {
-       case MPI25_MFGPAGE_DEVID_SAS3008:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT3SAS_INTEL_RMS3JC080_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_INTEL_RMS3JC080_BRANDING);
-                       break;
-
-               case MPT3SAS_INTEL_RS3GC008_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_INTEL_RS3GC008_BRANDING);
-                       break;
-               case MPT3SAS_INTEL_RS3FC044_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_INTEL_RS3FC044_BRANDING);
-                       break;
-               case MPT3SAS_INTEL_RS3UC080_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_INTEL_RS3UC080_BRANDING);
+       switch (ioc->pdev->subsystem_vendor) {
+       case PCI_VENDOR_ID_INTEL:
+               switch (ioc->pdev->device) {
+               case MPI2_MFGPAGE_DEVID_SAS2008:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT2SAS_INTEL_RMS2LL080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS2LL080_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS2LL040_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS2LL040_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_SSD910_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_SSD910_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                "Intel(R) Controller: Subsystem ID: 0x%X\n",
+                                ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
+               case MPI2_MFGPAGE_DEVID_SAS2308_2:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT2SAS_INTEL_RS25GB008_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RS25GB008_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25JB080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25JB080_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25JB040_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25JB040_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25KB080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25KB080_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25KB040_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25KB040_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25LB040_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25LB040_BRANDING);
+                               break;
+                       case MPT2SAS_INTEL_RMS25LB080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_INTEL_RMS25LB080_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                "Intel(R) Controller: Subsystem ID: 0x%X\n",
+                                ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
+               case MPI25_MFGPAGE_DEVID_SAS3008:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT3SAS_INTEL_RMS3JC080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_INTEL_RMS3JC080_BRANDING);
+                               break;
+
+                       case MPT3SAS_INTEL_RS3GC008_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_INTEL_RS3GC008_BRANDING);
+                               break;
+                       case MPT3SAS_INTEL_RS3FC044_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_INTEL_RS3FC044_BRANDING);
+                               break;
+                       case MPT3SAS_INTEL_RS3UC080_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_INTEL_RS3UC080_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                "Intel(R) Controller: Subsystem ID: 0x%X\n",
+                                ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
                        break;
                default:
                        pr_info(MPT3SAS_FMT
-                               "Intel(R) Controller: Subsystem ID: 0x%X\n",
-                               ioc->name, ioc->pdev->subsystem_device);
+                        "Intel(R) Controller: Subsystem ID: 0x%X\n",
+                        ioc->name, ioc->pdev->subsystem_device);
                        break;
                }
                break;
-       default:
-               pr_info(MPT3SAS_FMT
-                       "Intel(R) Controller: Subsystem ID: 0x%X\n",
-                       ioc->name, ioc->pdev->subsystem_device);
-               break;
-       }
-}
-
-
-
-/**
- * _base_display_dell_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_dell_branding(struct MPT3SAS_ADAPTER *ioc)
-{
-       if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
-               return;
-
-       switch (ioc->pdev->device) {
-       case MPI25_MFGPAGE_DEVID_SAS3008:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT3SAS_DELL_12G_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_DELL_12G_HBA_BRANDING);
+       case PCI_VENDOR_ID_DELL:
+               switch (ioc->pdev->device) {
+               case MPI2_MFGPAGE_DEVID_SAS2008:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_PERC_H200_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_PERC_H200_BRANDING);
+                               break;
+                       case MPT2SAS_DELL_6GBPS_SAS_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_DELL_6GBPS_SAS_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                  "Dell 6Gbps HBA: Subsystem ID: 0x%X\n",
+                                  ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
+                       break;
+               case MPI25_MFGPAGE_DEVID_SAS3008:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT3SAS_DELL_12G_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_DELL_12G_HBA_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                  "Dell 12Gbps HBA: Subsystem ID: 0x%X\n",
+                                  ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
                        break;
                default:
                        pr_info(MPT3SAS_FMT
-                          "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name,
+                          "Dell HBA: Subsystem ID: 0x%X\n", ioc->name,
                           ioc->pdev->subsystem_device);
                        break;
                }
                break;
-       default:
-               pr_info(MPT3SAS_FMT
-                       "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name,
-                       ioc->pdev->subsystem_device);
-               break;
-       }
-}
-
-/**
- * _base_display_cisco_branding - Display branding string
- * @ioc: per adapter object
- *
- * Return nothing.
- */
-static void
-_base_display_cisco_branding(struct MPT3SAS_ADAPTER *ioc)
-{
-       if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_CISCO)
-               return;
-
-       switch (ioc->pdev->device) {
-       case MPI25_MFGPAGE_DEVID_SAS3008:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT3SAS_CISCO_12G_8E_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_CISCO_12G_8E_HBA_BRANDING);
-                       break;
-               case MPT3SAS_CISCO_12G_8I_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                               MPT3SAS_CISCO_12G_8I_HBA_BRANDING);
+       case PCI_VENDOR_ID_CISCO:
+               switch (ioc->pdev->device) {
+               case MPI25_MFGPAGE_DEVID_SAS3008:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT3SAS_CISCO_12G_8E_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_CISCO_12G_8E_HBA_BRANDING);
+                               break;
+                       case MPT3SAS_CISCO_12G_8I_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_CISCO_12G_8I_HBA_BRANDING);
+                               break;
+                       case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                       MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                 "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
+                                 ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
                        break;
-               case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+               case MPI25_MFGPAGE_DEVID_SAS3108_1:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
                                MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
+                               break;
+                       case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                               MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING
+                               );
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
+                                ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
                        break;
                default:
                        pr_info(MPT3SAS_FMT
-                         "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
-                         ioc->name, ioc->pdev->subsystem_device);
+                          "Cisco SAS HBA: Subsystem ID: 0x%X\n",
+                          ioc->name, ioc->pdev->subsystem_device);
                        break;
                }
                break;
-       case MPI25_MFGPAGE_DEVID_SAS3108_1:
-               switch (ioc->pdev->subsystem_device) {
-               case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                       MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING);
-                       break;
-               case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID:
-                       pr_info(MPT3SAS_FMT "%s\n", ioc->name,
-                       MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING);
-                       break;
+       case MPT2SAS_HP_3PAR_SSVID:
+               switch (ioc->pdev->device) {
+               case MPI2_MFGPAGE_DEVID_SAS2004:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                  "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n",
+                                  ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
+               case MPI2_MFGPAGE_DEVID_SAS2308_2:
+                       switch (ioc->pdev->subsystem_device) {
+                       case MPT2SAS_HP_2_4_INTERNAL_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_HP_2_4_INTERNAL_BRANDING);
+                               break;
+                       case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
+                               break;
+                       case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
+                               break;
+                       case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
+                               pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+                                   MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
+                               break;
+                       default:
+                               pr_info(MPT3SAS_FMT
+                                  "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n",
+                                  ioc->name, ioc->pdev->subsystem_device);
+                               break;
+                       }
                default:
                        pr_info(MPT3SAS_FMT
-                        "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
-                        ioc->name, ioc->pdev->subsystem_device);
+                          "HP SAS HBA: Subsystem ID: 0x%X\n",
+                          ioc->name, ioc->pdev->subsystem_device);
                        break;
                }
-               break;
        default:
-                pr_info(MPT3SAS_FMT
-                       "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n",
-                       ioc->name, ioc->pdev->subsystem_device);
                break;
        }
 }
@@ -2488,9 +2800,7 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
           (bios_version & 0x0000FF00) >> 8,
            bios_version & 0x000000FF);
 
-       _base_display_intel_branding(ioc);
-       _base_display_dell_branding(ioc);
-       _base_display_cisco_branding(ioc);
+       _base_display_OEMs_branding(ioc);
 
        pr_info(MPT3SAS_FMT "Protocol=(", ioc->name);
 
@@ -2508,10 +2818,12 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc)
        pr_info("), ");
        pr_info("Capabilities=(");
 
-       if (ioc->facts.IOCCapabilities &
+       if (!ioc->hide_ir_msg) {
+               if (ioc->facts.IOCCapabilities &
                    MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
                        pr_info("Raid");
                        i++;
+               }
        }
 
        if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
@@ -2852,18 +3164,22 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc,  int sleep_flag)
        /* command line tunables for max sgl entries */
        if (max_sgl_entries != -1)
                sg_tablesize = max_sgl_entries;
-       else
-               sg_tablesize = MPT3SAS_SG_DEPTH;
+       else {
+               if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+                       sg_tablesize = MPT2SAS_SG_DEPTH;
+               else
+                       sg_tablesize = MPT3SAS_SG_DEPTH;
+       }
 
-       if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS)
-               sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS;
-       else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS) {
+       if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
+               sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+       else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
                sg_tablesize = min_t(unsigned short, sg_tablesize,
                                      SCSI_MAX_SG_CHAIN_SEGMENTS);
                pr_warn(MPT3SAS_FMT
                 "sg_tablesize(%u) is bigger than kernel"
                 " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name,
-                sg_tablesize, MPT3SAS_MAX_PHYS_SEGMENTS);
+                sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
        }
        ioc->shost->sg_tablesize = sg_tablesize;
 
@@ -4021,7 +4337,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
        mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
        mpi_request.VF_ID = 0; /* TODO */
        mpi_request.VP_ID = 0;
-       mpi_request.MsgVersion = cpu_to_le16(MPI25_VERSION);
+       mpi_request.MsgVersion = cpu_to_le16(ioc->hba_mpi_version_belonged);
        mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
 
        if (_base_is_controller_msix_enabled(ioc))
@@ -4655,6 +4971,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
        u32 reply_address;
        u16 smid;
        struct _tr_list *delayed_tr, *delayed_tr_next;
+       u8 hide_flag;
        struct adapter_reply_queue *reply_q;
        long reply_post_free;
        u32 reply_post_free_sz, index = 0;
@@ -4685,6 +5002,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
                ioc->scsi_lookup[i].cb_idx = 0xFF;
                ioc->scsi_lookup[i].smid = smid;
                ioc->scsi_lookup[i].scmd = NULL;
+               ioc->scsi_lookup[i].direct_io = 0;
                list_add_tail(&ioc->scsi_lookup[i].tracker_list,
                    &ioc->free_list);
        }
@@ -4787,6 +5105,16 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
 
 
        if (ioc->is_driver_loading) {
+
+               if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
+                   == 0x80) {
+                       hide_flag = (u8) (
+                           le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) &
+                           MFG_PAGE10_HIDE_SSDS_MASK);
+                       if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK)
+                               ioc->mfg_pg10_hide_flag = hide_flag;
+               }
+
                ioc->wait_for_discovery_to_complete =
                    _base_determine_wait_on_discovery(ioc);
 
@@ -4812,6 +5140,8 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
        dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
            __func__));
 
+       /* synchronizing freeing resource with pci_access_mutex lock */
+       mutex_lock(&ioc->pci_access_mutex);
        if (ioc->chip_phys && ioc->chip) {
                _base_mask_interrupts(ioc);
                ioc->shost_recovery = 1;
@@ -4820,6 +5150,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc)
        }
 
        mpt3sas_base_unmap_resources(ioc);
+       mutex_unlock(&ioc->pci_access_mutex);
        return;
 }
 
@@ -4834,7 +5165,6 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
 {
        int r, i;
        int cpu_id, last_cpu_id = 0;
-       u8 revision;
 
        dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
            __func__));
@@ -4854,19 +5184,16 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
                goto out_free_resources;
        }
 
-       /* Check whether the controller revision is C0 or above.
-        * only C0 and above revision controllers support 96 MSI-X vectors.
-        */
-       revision = ioc->pdev->revision;
-
-       if ((ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3004 ||
-            ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3008 ||
-            ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_1 ||
-            ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_2 ||
-            ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_5 ||
-            ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_6) &&
-            (revision >= 0x02))
-               ioc->msix96_vector = 1;
+       if (ioc->is_warpdrive) {
+               ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
+                   sizeof(resource_size_t *), GFP_KERNEL);
+               if (!ioc->reply_post_host_index) {
+                       dfailprintk(ioc, pr_info(MPT3SAS_FMT "allocation "
+                               "for cpu_msix_table failed!!!\n", ioc->name));
+                       r = -ENOMEM;
+                       goto out_free_resources;
+               }
+       }
 
        ioc->rdpq_array_enable_assigned = 0;
        ioc->dma_mask = 0;
@@ -4874,23 +5201,41 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
        if (r)
                goto out_free_resources;
 
+       if (ioc->is_warpdrive) {
+               ioc->reply_post_host_index[0] = (resource_size_t __iomem *)
+                   &ioc->chip->ReplyPostHostIndex;
+
+               for (i = 1; i < ioc->cpu_msix_table_sz; i++)
+                       ioc->reply_post_host_index[i] =
+                       (resource_size_t __iomem *)
+                       ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1)
+                       * 4)));
+       }
 
        pci_set_drvdata(ioc->pdev, ioc->shost);
        r = _base_get_ioc_facts(ioc, CAN_SLEEP);
        if (r)
                goto out_free_resources;
 
-       /*
-        * In SAS3.0,
-        * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
-        * Target Status - all require the IEEE formated scatter gather
-        * elements.
-        */
-
-       ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
-       ioc->build_sg = &_base_build_sg_ieee;
-       ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
-       ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
+       switch (ioc->hba_mpi_version_belonged) {
+       case MPI2_VERSION:
+               ioc->build_sg_scmd = &_base_build_sg_scmd;
+               ioc->build_sg = &_base_build_sg;
+               ioc->build_zero_len_sge = &_base_build_zero_len_sge;
+               break;
+       case MPI25_VERSION:
+               /*
+                * In SAS3.0,
+                * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and
+                * Target Status - all require the IEEE formated scatter gather
+                * elements.
+                */
+               ioc->build_sg_scmd = &_base_build_sg_scmd_ieee;
+               ioc->build_sg = &_base_build_sg_ieee;
+               ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee;
+               ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t);
+               break;
+       }
 
        /*
         * These function pointers for other requests that don't
@@ -5006,6 +5351,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
        if (r)
                goto out_free_resources;
 
+       ioc->non_operational_loop = 0;
        return 0;
 
  out_free_resources:
@@ -5016,6 +5362,8 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
        _base_release_memory_pools(ioc);
        pci_set_drvdata(ioc->pdev, NULL);
        kfree(ioc->cpu_msix_table);
+       if (ioc->is_warpdrive)
+               kfree(ioc->reply_post_host_index);
        kfree(ioc->pd_handles);
        kfree(ioc->blocking_handles);
        kfree(ioc->tm_cmds.reply);
@@ -5055,6 +5403,8 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
        _base_release_memory_pools(ioc);
        pci_set_drvdata(ioc->pdev, NULL);
        kfree(ioc->cpu_msix_table);
+       if (ioc->is_warpdrive)
+               kfree(ioc->reply_post_host_index);
        kfree(ioc->pd_handles);
        kfree(ioc->blocking_handles);
        kfree(ioc->pfacts);
index f0e462b0880d21a645327bf60c221cc0f112c76a..5ad271efbd45e760eabd72d8218bd6cefc6a0e23 100644 (file)
@@ -63,6 +63,8 @@
 #include <scsi/scsi_transport_sas.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_eh.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
 
 #include "mpt3sas_debug.h"
 #include "mpt3sas_trigger_diag.h"
 #define MPT3SAS_DRIVER_NAME            "mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
 #define MPT3SAS_DESCRIPTION    "LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION         "09.100.00.00"
+#define MPT3SAS_DRIVER_VERSION         "09.102.00.00"
 #define MPT3SAS_MAJOR_VERSION          9
-#define MPT3SAS_MINOR_VERSION          100
+#define MPT3SAS_MINOR_VERSION          102
 #define MPT3SAS_BUILD_VERSION          0
 #define MPT3SAS_RELEASE_VERSION        00
 
+#define MPT2SAS_DRIVER_NAME            "mpt2sas"
+#define MPT2SAS_DESCRIPTION    "LSI MPT Fusion SAS 2.0 Device Driver"
+#define MPT2SAS_DRIVER_VERSION         "20.102.00.00"
+#define MPT2SAS_MAJOR_VERSION          20
+#define MPT2SAS_MINOR_VERSION          102
+#define MPT2SAS_BUILD_VERSION          0
+#define MPT2SAS_RELEASE_VERSION        00
+
 /*
  * Set MPT3SAS_SG_DEPTH value based on user input.
  */
-#define MPT3SAS_MAX_PHYS_SEGMENTS      SCSI_MAX_SG_SEGMENTS
-#define MPT3SAS_MIN_PHYS_SEGMENTS      16
+#define MPT_MAX_PHYS_SEGMENTS  SCSI_MAX_SG_SEGMENTS
+#define MPT_MIN_PHYS_SEGMENTS  16
+
 #ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE
 #define MPT3SAS_SG_DEPTH               CONFIG_SCSI_MPT3SAS_MAX_SGE
 #else
-#define MPT3SAS_SG_DEPTH               MPT3SAS_MAX_PHYS_SEGMENTS
+#define MPT3SAS_SG_DEPTH               MPT_MAX_PHYS_SEGMENTS
 #endif
 
+#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
+#define MPT2SAS_SG_DEPTH               CONFIG_SCSI_MPT2SAS_MAX_SGE
+#else
+#define MPT2SAS_SG_DEPTH               MPT_MAX_PHYS_SEGMENTS
+#endif
 
 /*
  * Generic Defines
  */
 #define MPT3SAS_FMT                    "%s: "
 
+/*
+ *  WarpDrive Specific Log codes
+ */
+
+#define MPT2_WARPDRIVE_LOGENTRY                (0x8002)
+#define MPT2_WARPDRIVE_LC_SSDT                 (0x41)
+#define MPT2_WARPDRIVE_LC_SSDLW                (0x43)
+#define MPT2_WARPDRIVE_LC_SSDLF                (0x44)
+#define MPT2_WARPDRIVE_LC_BRMF                 (0x4D)
+
 /*
  * per target private data
  */
 #define MPT_TARGET_FLAGS_DELETED       0x04
 #define MPT_TARGET_FASTPATH_IO         0x08
 
+#define SAS2_PCI_DEVICE_B0_REVISION    (0x01)
+#define SAS3_PCI_DEVICE_C0_REVISION    (0x02)
+
 /*
  * Intel HBA branding
  */
+#define MPT2SAS_INTEL_RMS25JB080_BRANDING    \
+       "Intel(R) Integrated RAID Module RMS25JB080"
+#define MPT2SAS_INTEL_RMS25JB040_BRANDING    \
+       "Intel(R) Integrated RAID Module RMS25JB040"
+#define MPT2SAS_INTEL_RMS25KB080_BRANDING    \
+       "Intel(R) Integrated RAID Module RMS25KB080"
+#define MPT2SAS_INTEL_RMS25KB040_BRANDING    \
+       "Intel(R) Integrated RAID Module RMS25KB040"
+#define MPT2SAS_INTEL_RMS25LB040_BRANDING      \
+       "Intel(R) Integrated RAID Module RMS25LB040"
+#define MPT2SAS_INTEL_RMS25LB080_BRANDING      \
+       "Intel(R) Integrated RAID Module RMS25LB080"
+#define MPT2SAS_INTEL_RMS2LL080_BRANDING       \
+       "Intel Integrated RAID Module RMS2LL080"
+#define MPT2SAS_INTEL_RMS2LL040_BRANDING       \
+       "Intel Integrated RAID Module RMS2LL040"
+#define MPT2SAS_INTEL_RS25GB008_BRANDING       \
+       "Intel(R) RAID Controller RS25GB008"
+#define MPT2SAS_INTEL_SSD910_BRANDING          \
+       "Intel(R) SSD 910 Series"
+
 #define MPT3SAS_INTEL_RMS3JC080_BRANDING       \
        "Intel(R) Integrated RAID Module RMS3JC080"
 #define MPT3SAS_INTEL_RS3GC008_BRANDING       \
 /*
  * Intel HBA SSDIDs
  */
-#define MPT3SAS_INTEL_RMS3JC080_SSDID  0x3521
-#define MPT3SAS_INTEL_RS3GC008_SSDID   0x3522
-#define MPT3SAS_INTEL_RS3FC044_SSDID   0x3523
-#define MPT3SAS_INTEL_RS3UC080_SSDID    0x3524
+#define MPT2SAS_INTEL_RMS25JB080_SSDID         0x3516
+#define MPT2SAS_INTEL_RMS25JB040_SSDID         0x3517
+#define MPT2SAS_INTEL_RMS25KB080_SSDID         0x3518
+#define MPT2SAS_INTEL_RMS25KB040_SSDID         0x3519
+#define MPT2SAS_INTEL_RMS25LB040_SSDID         0x351A
+#define MPT2SAS_INTEL_RMS25LB080_SSDID         0x351B
+#define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
+#define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
+#define MPT2SAS_INTEL_RS25GB008_SSDID          0x3000
+#define MPT2SAS_INTEL_SSD910_SSDID             0x3700
+
+#define MPT3SAS_INTEL_RMS3JC080_SSDID          0x3521
+#define MPT3SAS_INTEL_RS3GC008_SSDID           0x3522
+#define MPT3SAS_INTEL_RS3FC044_SSDID           0x3523
+#define MPT3SAS_INTEL_RS3UC080_SSDID           0x3524
 
 /*
  * Dell HBA branding
  */
+#define MPT2SAS_DELL_BRANDING_SIZE                 32
+
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING        "Dell 6Gbps SAS HBA"
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING    "Dell PERC H200 Adapter"
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
+#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING    "Dell PERC H200 Modular"
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING   "Dell PERC H200 Embedded"
+#define MPT2SAS_DELL_PERC_H200_BRANDING            "Dell PERC H200"
+#define MPT2SAS_DELL_6GBPS_SAS_BRANDING            "Dell 6Gbps SAS"
+
 #define MPT3SAS_DELL_12G_HBA_BRANDING       \
        "Dell 12Gbps HBA"
 
 /*
  * Dell HBA SSDIDs
  */
-#define MPT3SAS_DELL_12G_HBA_SSDID     0x1F46
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID       0x1F1C
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID   0x1F1D
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID        0x1F1E
+#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID   0x1F1F
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID  0x1F20
+#define MPT2SAS_DELL_PERC_H200_SSDID           0x1F21
+#define MPT2SAS_DELL_6GBPS_SAS_SSDID           0x1F22
+
+#define MPT3SAS_DELL_12G_HBA_SSDID             0x1F46
 
 /*
  * Cisco HBA branding
  */
 #define MPT3SAS_CISCO_12G_8E_HBA_BRANDING              \
-               "Cisco 9300-8E 12G SAS HBA"
+       "Cisco 9300-8E 12G SAS HBA"
 #define MPT3SAS_CISCO_12G_8I_HBA_BRANDING              \
-               "Cisco 9300-8i 12G SAS HBA"
+       "Cisco 9300-8i 12G SAS HBA"
 #define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING   \
-               "Cisco 12G Modular SAS Pass through Controller"
+       "Cisco 12G Modular SAS Pass through Controller"
 #define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING                \
-               "UCS C3X60 12G SAS Pass through Controller"
+       "UCS C3X60 12G SAS Pass through Controller"
 /*
  * Cisco HBA SSSDIDs
  */
 #define MPT3_DIAG_BUFFER_IS_RELEASED   (0x02)
 #define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
 
+/*
+ * HP HBA branding
+ */
+#define MPT2SAS_HP_3PAR_SSVID                0x1590
+
+#define MPT2SAS_HP_2_4_INTERNAL_BRANDING       \
+       "HP H220 Host Bus Adapter"
+#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING       \
+       "HP H221 Host Bus Adapter"
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING  \
+       "HP H222 Host Bus Adapter"
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING      \
+       "HP H220i Host Bus Adapter"
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING      \
+       "HP H210i Host Bus Adapter"
+
+/*
+ * HO HBA SSDIDs
+ */
+#define MPT2SAS_HP_2_4_INTERNAL_SSDID                  0x0041
+#define MPT2SAS_HP_2_4_EXTERNAL_SSDID                  0x0042
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID     0x0043
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID         0x0044
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID         0x0046
+
 /*
  * Combined Reply Queue constants,
  * There are twelve Supplemental Reply Post Host Index Registers
@@ -243,20 +347,24 @@ struct Mpi2ManufacturingPage11_t {
  * struct MPT3SAS_TARGET - starget private hostdata
  * @starget: starget object
  * @sas_address: target sas address
+ * @raid_device: raid_device pointer to access volume data
  * @handle: device handle
  * @num_luns: number luns
  * @flags: MPT_TARGET_FLAGS_XXX flags
  * @deleted: target flaged for deletion
  * @tm_busy: target is busy with TM request.
+ * @sdev: The sas_device associated with this target
  */
 struct MPT3SAS_TARGET {
        struct scsi_target *starget;
        u64     sas_address;
+       struct _raid_device *raid_device;
        u16     handle;
        int     num_luns;
        u32     flags;
        u8      deleted;
        u8      tm_busy;
+       struct _sas_device *sdev;
 };
 
 
@@ -266,6 +374,11 @@ struct MPT3SAS_TARGET {
 #define MPT_DEVICE_FLAGS_INIT          0x01
 #define MPT_DEVICE_TLR_ON              0x02
 
+#define MFG_PAGE10_HIDE_SSDS_MASK      (0x00000003)
+#define MFG_PAGE10_HIDE_ALL_DISKS      (0x00)
+#define MFG_PAGE10_EXPOSE_ALL_DISKS    (0x01)
+#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02)
+
 /**
  * struct MPT3SAS_DEVICE - sdev private hostdata
  * @sas_target: starget private hostdata
@@ -358,8 +471,24 @@ struct _sas_device {
        u8      pend_sas_rphy_add;
        u8      enclosure_level;
        u8      connector_name[4];
+       struct kref refcount;
 };
 
+static inline void sas_device_get(struct _sas_device *s)
+{
+       kref_get(&s->refcount);
+}
+
+static inline void sas_device_free(struct kref *r)
+{
+       kfree(container_of(r, struct _sas_device, refcount));
+}
+
+static inline void sas_device_put(struct _sas_device *s)
+{
+       kref_put(&s->refcount, sas_device_free);
+}
+
 /**
  * struct _raid_device - raid volume link list
  * @list: sas device list
@@ -367,6 +496,7 @@ struct _sas_device {
  * @sdev: scsi device struct (volumes are single lun)
  * @wwid: unique identifier for the volume
  * @handle: device handle
+ * @block_size: Block size of the volume
  * @id: target id
  * @channel: target channel
  * @volume_type: the raid level
@@ -374,6 +504,13 @@ struct _sas_device {
  * @num_pds: number of hidden raid components
  * @responding: used in _scsih_raid_device_mark_responding
  * @percent_complete: resync percent complete
+ * @direct_io_enabled: Whether direct io to PDs are allowed or not
+ * @stripe_exponent: X where 2powX is the stripe sz in blocks
+ * @block_exponent: X where 2powX is the block sz in bytes
+ * @max_lba: Maximum number of LBA in the volume
+ * @stripe_sz: Stripe Size of the volume
+ * @device_info: Device info of the volume member disk
+ * @pd_handle: Array of handles of the physical drives for direct I/O in le16
  */
 #define MPT_MAX_WARPDRIVE_PDS          8
 struct _raid_device {
@@ -382,13 +519,20 @@ struct _raid_device {
        struct scsi_device *sdev;
        u64     wwid;
        u16     handle;
+       u16     block_sz;
        int     id;
        int     channel;
        u8      volume_type;
        u8      num_pds;
        u8      responding;
        u8      percent_complete;
+       u8      direct_io_enabled;
+       u8      stripe_exponent;
+       u8      block_exponent;
+       u64     max_lba;
+       u32     stripe_sz;
        u32     device_info;
+       u16     pd_handle[MPT_MAX_WARPDRIVE_PDS];
 };
 
 /**
@@ -497,12 +641,14 @@ struct chain_tracker {
  * @smid: system message id
  * @scmd: scsi request pointer
  * @cb_idx: callback index
+ * @direct_io: To indicate whether I/O is direct (WARPDRIVE)
  * @tracker_list: list of free request (ioc->free_list)
  */
 struct scsiio_tracker {
        u16     smid;
        struct scsi_cmnd *scmd;
        u8      cb_idx;
+       u8      direct_io;
        struct list_head chain_list;
        struct list_head tracker_list;
 };
@@ -775,7 +921,13 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
  * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue
  * @delayed_tr_list: target reset link list
  * @delayed_tr_volume_list: volume target reset link list
- * @@temp_sensors_count: flag to carry the number of temperature sensors
+ * @temp_sensors_count: flag to carry the number of temperature sensors
+ * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and
+ *     pci resource handling. PCI resource freeing will lead to free
+ *     vital hardware/memory resource, which might be in use by cli/sysfs
+ *     path functions resulting in Null pointer reference followed by kernel
+ *     crash. To avoid the above race condition we use mutex syncrhonization
+ *     which ensures the syncrhonization between cli/sysfs_show path.
  */
 struct MPT3SAS_ADAPTER {
        struct list_head list;
@@ -783,6 +935,7 @@ struct MPT3SAS_ADAPTER {
        u8              id;
        int             cpu_count;
        char            name[MPT_NAME_LENGTH];
+       char            driver_name[MPT_NAME_LENGTH];
        char            tmp_string[MPT_STRING_LENGTH];
        struct pci_dev  *pdev;
        Mpi2SystemInterfaceRegs_t __iomem *chip;
@@ -829,8 +982,10 @@ struct MPT3SAS_ADAPTER {
        u16             msix_vector_count;
        u8              *cpu_msix_table;
        u16             cpu_msix_table_sz;
+       resource_size_t __iomem **reply_post_host_index;
        u32             ioc_reset_count;
        MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
+       u32             non_operational_loop;
 
        /* internal commands, callback index */
        u8              scsi_io_cb_idx;
@@ -859,6 +1014,7 @@ struct MPT3SAS_ADAPTER {
        MPT_BUILD_SG    build_sg;
        MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge;
        u16             sge_size_ieee;
+       u16             hba_mpi_version_belonged;
 
        /* function ptr for MPI sg elements only */
        MPT_BUILD_SG    build_sg_mpi;
@@ -987,6 +1143,7 @@ struct MPT3SAS_ADAPTER {
        struct list_head delayed_tr_list;
        struct list_head delayed_tr_volume_list;
        u8              temp_sensors_count;
+       struct mutex pci_access_mutex;
 
        /* diag buffer support */
        u8              *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
@@ -998,6 +1155,10 @@ struct MPT3SAS_ADAPTER {
        u32             diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
        u32             ring_buffer_offset;
        u32             ring_buffer_sz;
+       u8              is_warpdrive;
+       u8              hide_ir_msg;
+       u8              mfg_pg10_hide_flag;
+       u8              hide_drives;
        spinlock_t      diag_trigger_lock;
        u8              diag_trigger_active;
        struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
@@ -1012,6 +1173,19 @@ typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
 
 /* base shared API */
 extern struct list_head mpt3sas_ioc_list;
+extern char    driver_name[MPT_NAME_LENGTH];
+/* spinlock on list operations over IOCs
+ * Case: when multiple warpdrive cards(IOCs) are in use
+ * Each IOC will added to the ioc list structure on initialization.
+ * Watchdog threads run at regular intervals to check IOC for any
+ * fault conditions which will trigger the dead_ioc thread to
+ * deallocate pci resource, resulting deleting the IOC netry from list,
+ * this deletion need to protected by spinlock to enusre that
+ * ioc removal is syncrhonized, if not synchronized it might lead to
+ * list_del corruption as the ioc list is traversed in cli path.
+ */
+extern spinlock_t gioc_lock;
+
 void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc);
 void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc);
 
@@ -1090,10 +1264,14 @@ struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
        struct MPT3SAS_ADAPTER *ioc, u16 handle);
 struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
        struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
-struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address(
-       struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *mpt3sas_get_sdev_by_addr(
+        struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *__mpt3sas_get_sdev_by_addr(
+        struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
 
 void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
+struct _raid_device *
+mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 
 /* config shared API */
 u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
@@ -1133,6 +1311,8 @@ int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
        u16 sz);
 int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        *mpi_reply, Mpi2IOUnitPage1_t *config_page);
+int mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz);
 int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        *mpi_reply, Mpi2IOUnitPage1_t *config_page);
 int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t
@@ -1177,8 +1357,8 @@ int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc,
 /* ctl shared API */
 extern struct device_attribute *mpt3sas_host_attrs[];
 extern struct device_attribute *mpt3sas_dev_attrs[];
-void mpt3sas_ctl_init(void);
-void mpt3sas_ctl_exit(void);
+void mpt3sas_ctl_init(ushort hbas_to_enumerate);
+void mpt3sas_ctl_exit(ushort hbas_to_enumerate);
 u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
        u32 reply);
 void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
@@ -1193,6 +1373,7 @@ int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
        u8 *issue_reset);
 
 /* transport shared API */
+extern struct scsi_transport_template *mpt3sas_transport_template;
 u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
        u32 reply);
 struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc,
@@ -1224,4 +1405,18 @@ void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key,
        u8 asc, u8 ascq);
 void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status,
        u32 loginfo);
+
+/* warpdrive APIs */
+u8 mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
+       struct _raid_device *raid_device);
+u8
+mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid);
+void
+mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io);
+void
+mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+       struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
+       u16 smid);
+
 #endif /* MPT3SAS_BASE_H_INCLUDED */
index e45c4613ef0c3a4a61aca89f5e18d3ba9f4d19d6..a6914ec99cc047ecb492e107988a1f5bb9551c1e 100644 (file)
@@ -83,7 +83,6 @@ struct config_request {
        dma_addr_t              page_dma;
 };
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _config_display_some_debug - debug routine
  * @ioc: per adapter object
@@ -173,7 +172,6 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
                    ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
                    le32_to_cpu(mpi_reply->IOCLogInfo));
 }
-#endif
 
 /**
  * _config_alloc_config_dma_memory - obtain physical memory
@@ -255,9 +253,7 @@ mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
                    mpi_reply->MsgLength*4);
        }
        ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
-#endif
        ioc->config_cmds.smid = USHRT_MAX;
        complete(&ioc->config_cmds.done);
        return 1;
@@ -387,9 +383,7 @@ _config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        config_request = mpt3sas_base_get_msg_frame(ioc, smid);
        ioc->config_cmds.smid = smid;
        memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        _config_display_some_debug(ioc, smid, "config_request", NULL);
-#endif
        init_completion(&ioc->config_cmds.done);
        mpt3sas_base_put_smid_default(ioc, smid);
        timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
@@ -871,6 +865,42 @@ mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc,
        return r;
 }
 
+/**
+ * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc,
+       Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz)
+{
+       Mpi2ConfigRequest_t mpi_request;
+       int r;
+
+       memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_CONFIG;
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+       mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+       mpi_request.Header.PageNumber = 3;
+       mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION;
+       ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+       if (r)
+               goto out;
+
+       mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+       r = _config_request(ioc, &mpi_request, mpi_reply,
+           MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz);
+ out:
+       return r;
+}
+
 /**
  * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8
  * @ioc: per adapter object
index 080c8a76d23d65c688f1a3e8fe5dbed8b90c4ac8..d8366b056b70f48c046b1fcb06637f70174914ee 100644 (file)
@@ -78,7 +78,6 @@ enum block_state {
        BLOCKING,
 };
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _ctl_sas_device_find_by_handle - sas device search
  * @ioc: per adapter object
@@ -254,8 +253,6 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
        }
 }
 
-#endif
-
 /**
  * mpt3sas_ctl_done - ctl module completion routine
  * @ioc: per adapter object
@@ -302,9 +299,7 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
                        }
                }
        }
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
-#endif
        ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING;
        complete(&ioc->ctl_cmds.done);
        return 1;
@@ -414,20 +409,31 @@ mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
  * _ctl_verify_adapter - validates ioc_number passed from application
  * @ioc: per adapter object
  * @iocpp: The ioc pointer is returned in this.
+ * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
+ *             MPI25_VERSION for mpt3ctl ioctl device.
  *
  * Return (-1) means error, else ioc_number.
  */
 static int
-_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp)
+_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp,
+                                                       int mpi_version)
 {
        struct MPT3SAS_ADAPTER *ioc;
-
+       /* global ioc lock to protect controller on list operations */
+       spin_lock(&gioc_lock);
        list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
                if (ioc->id != ioc_number)
                        continue;
+               /* Check whether this ioctl command is from right
+                * ioctl device or not, if not continue the search.
+                */
+               if (ioc->hba_mpi_version_belonged != mpi_version)
+                       continue;
+               spin_unlock(&gioc_lock);
                *iocpp = ioc;
                return ioc_number;
        }
+       spin_unlock(&gioc_lock);
        *iocpp = NULL;
        return -1;
 }
@@ -497,7 +503,7 @@ mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
  *
  * Called when application request fasyn callback handler.
  */
-static int
+int
 _ctl_fasync(int fd, struct file *filep, int mode)
 {
        return fasync_helper(fd, filep, mode, &async_queue);
@@ -509,17 +515,22 @@ _ctl_fasync(int fd, struct file *filep, int mode)
  * @wait -
  *
  */
-static unsigned int
+unsigned int
 _ctl_poll(struct file *filep, poll_table *wait)
 {
        struct MPT3SAS_ADAPTER *ioc;
 
        poll_wait(filep, &ctl_poll_wait, wait);
 
+       /* global ioc lock to protect controller on list operations */
+       spin_lock(&gioc_lock);
        list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
-               if (ioc->aen_event_read_flag)
+               if (ioc->aen_event_read_flag) {
+                       spin_unlock(&gioc_lock);
                        return POLLIN | POLLRDNORM;
+               }
        }
+       spin_unlock(&gioc_lock);
        return 0;
 }
 
@@ -759,9 +770,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
        psge = (void *)request + (karg.data_sge_offset*4);
 
        /* send command to firmware */
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
-#endif
 
        init_completion(&ioc->ctl_cmds.done);
        switch (mpi_request->Function) {
@@ -916,7 +925,6 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
        mpi_reply = ioc->ctl_cmds.reply;
        ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
            (ioc->logging_level & MPT_DEBUG_TM)) {
                Mpi2SCSITaskManagementReply_t *tm_reply =
@@ -929,7 +937,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
                    le32_to_cpu(tm_reply->IOCLogInfo),
                    le32_to_cpu(tm_reply->TerminationCount));
        }
-#endif
+
        /* copy out xdata to user */
        if (data_in_sz) {
                if (copy_to_user(karg.data_in_buf_ptr, data_in,
@@ -1023,7 +1031,6 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
            __func__));
 
        memset(&karg, 0 , sizeof(karg));
-       karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
        if (ioc->pfacts)
                karg.port_number = ioc->pfacts[0].PortNumber;
        karg.hw_rev = ioc->pdev->revision;
@@ -1035,9 +1042,21 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
        karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
        karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
        karg.firmware_version = ioc->facts.FWVersion.Word;
-       strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME);
+       strcpy(karg.driver_version, ioc->driver_name);
        strcat(karg.driver_version, "-");
-       strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
+       switch  (ioc->hba_mpi_version_belonged) {
+       case MPI2_VERSION:
+               if (ioc->is_warpdrive)
+                       karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200;
+               else
+                       karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
+               strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
+               break;
+       case MPI25_VERSION:
+               karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
+               strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
+               break;
+       }
        karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
 
        if (copy_to_user(arg, &karg, sizeof(karg))) {
@@ -2181,12 +2200,14 @@ _ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
  * _ctl_ioctl_main - main ioctl entry point
  * @file - (struct file)
  * @cmd - ioctl opcode
- * @arg -
- * compat - handles 32 bit applications in 64bit os
+ * @arg - user space data buffer
+ * @compat - handles 32 bit applications in 64bit os
+ * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
+ *             MPI25_VERSION for mpt3ctl ioctl device.
  */
 static long
 _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
-       u8 compat)
+       u8 compat, u16 mpi_version)
 {
        struct MPT3SAS_ADAPTER *ioc;
        struct mpt3_ioctl_header ioctl_header;
@@ -2201,19 +2222,29 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
                return -EFAULT;
        }
 
-       if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc)
+       if (_ctl_verify_adapter(ioctl_header.ioc_number,
+                               &ioc, mpi_version) == -1 || !ioc)
                return -ENODEV;
 
+       /* pci_access_mutex lock acquired by ioctl path */
+       mutex_lock(&ioc->pci_access_mutex);
+
        if (ioc->shost_recovery || ioc->pci_error_recovery ||
-           ioc->is_driver_loading)
-               return -EAGAIN;
+           ioc->is_driver_loading || ioc->remove_host) {
+               ret = -EAGAIN;
+               goto out_unlock_pciaccess;
+       }
 
        state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
        if (state == NON_BLOCKING) {
-               if (!mutex_trylock(&ioc->ctl_cmds.mutex))
-                       return -EAGAIN;
-       } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
-               return -ERESTARTSYS;
+               if (!mutex_trylock(&ioc->ctl_cmds.mutex)) {
+                       ret = -EAGAIN;
+                       goto out_unlock_pciaccess;
+               }
+       } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) {
+               ret = -ERESTARTSYS;
+               goto out_unlock_pciaccess;
+       }
 
 
        switch (cmd) {
@@ -2294,39 +2325,78 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
        }
 
        mutex_unlock(&ioc->ctl_cmds.mutex);
+out_unlock_pciaccess:
+       mutex_unlock(&ioc->pci_access_mutex);
        return ret;
 }
 
 /**
- * _ctl_ioctl - main ioctl entry point (unlocked)
+ * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked)
  * @file - (struct file)
  * @cmd - ioctl opcode
  * @arg -
  */
-static long
+long
 _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        long ret;
 
-       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0);
+       /* pass MPI25_VERSION value, to indicate that this ioctl cmd
+        * came from mpt3ctl ioctl device.
+        */
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI25_VERSION);
        return ret;
 }
 
+/**
+ * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked)
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ */
+long
+_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+
+       /* pass MPI2_VERSION value, to indicate that this ioctl cmd
+        * came from mpt2ctl ioctl device.
+        */
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION);
+       return ret;
+}
 #ifdef CONFIG_COMPAT
 /**
- * _ctl_ioctl_compat - main ioctl entry point (compat)
+ *ctl_ioctl_compat - main ioctl entry point (compat)
  * @file -
  * @cmd -
  * @arg -
  *
  * This routine handles 32 bit applications in 64bit os.
  */
-static long
+long
 _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
 {
        long ret;
 
-       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1);
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI25_VERSION);
+       return ret;
+}
+
+/**
+ *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat)
+ * @file -
+ * @cmd -
+ * @arg -
+ *
+ * This routine handles 32 bit applications in 64bit os.
+ */
+long
+_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
+{
+       long ret;
+
+       ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION);
        return ret;
 }
 #endif
@@ -2713,6 +2783,82 @@ _ctl_ioc_reply_queue_count_show(struct device *cdev,
 static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show,
        NULL);
 
+/**
+ * _ctl_BRM_status_show - Backup Rail Monitor Status
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is number of reply queues
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr,
+       char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+       Mpi2IOUnitPage3_t *io_unit_pg3 = NULL;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 backup_rail_monitor_status = 0;
+       u16 ioc_status;
+       int sz;
+       ssize_t rc = 0;
+
+       if (!ioc->is_warpdrive) {
+               pr_err(MPT3SAS_FMT "%s: BRM attribute is only for"
+                   " warpdrive\n", ioc->name, __func__);
+               goto out;
+       }
+       /* pci_access_mutex lock acquired by sysfs show path */
+       mutex_lock(&ioc->pci_access_mutex);
+       if (ioc->pci_error_recovery || ioc->remove_host) {
+               mutex_unlock(&ioc->pci_access_mutex);
+               return 0;
+       }
+
+       /* allocate upto GPIOVal 36 entries */
+       sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36);
+       io_unit_pg3 = kzalloc(sz, GFP_KERNEL);
+       if (!io_unit_pg3) {
+               pr_err(MPT3SAS_FMT "%s: failed allocating memory "
+                   "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz);
+               goto out;
+       }
+
+       if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) !=
+           0) {
+               pr_err(MPT3SAS_FMT
+                   "%s: failed reading iounit_pg3\n", ioc->name,
+                   __func__);
+               goto out;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               pr_err(MPT3SAS_FMT "%s: iounit_pg3 failed with "
+                   "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status);
+               goto out;
+       }
+
+       if (io_unit_pg3->GPIOCount < 25) {
+               pr_err(MPT3SAS_FMT "%s: iounit_pg3->GPIOCount less than "
+                    "25 entries, detected (%d) entries\n", ioc->name, __func__,
+                   io_unit_pg3->GPIOCount);
+               goto out;
+       }
+
+       /* BRM status is in bit zero of GPIOVal[24] */
+       backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]);
+       rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1));
+
+ out:
+       kfree(io_unit_pg3);
+       mutex_unlock(&ioc->pci_access_mutex);
+       return rc;
+}
+static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL);
+
 struct DIAG_BUFFER_START {
        __le32  Size;
        __le32  DiagVersion;
@@ -3165,6 +3311,7 @@ struct device_attribute *mpt3sas_host_attrs[] = {
        &dev_attr_diag_trigger_event,
        &dev_attr_diag_trigger_scsi,
        &dev_attr_diag_trigger_mpi,
+       &dev_attr_BRM_status,
        NULL,
 };
 
@@ -3218,6 +3365,7 @@ struct device_attribute *mpt3sas_dev_attrs[] = {
        NULL,
 };
 
+/* file operations table for mpt3ctl device */
 static const struct file_operations ctl_fops = {
        .owner = THIS_MODULE,
        .unlocked_ioctl = _ctl_ioctl,
@@ -3228,23 +3376,53 @@ static const struct file_operations ctl_fops = {
 #endif
 };
 
+/* file operations table for mpt2ctl device */
+static const struct file_operations ctl_gen2_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = _ctl_mpt2_ioctl,
+       .poll = _ctl_poll,
+       .fasync = _ctl_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = _ctl_mpt2_ioctl_compat,
+#endif
+};
+
 static struct miscdevice ctl_dev = {
        .minor  = MPT3SAS_MINOR,
        .name   = MPT3SAS_DEV_NAME,
        .fops   = &ctl_fops,
 };
 
+static struct miscdevice gen2_ctl_dev = {
+       .minor  = MPT2SAS_MINOR,
+       .name   = MPT2SAS_DEV_NAME,
+       .fops   = &ctl_gen2_fops,
+};
+
 /**
  * mpt3sas_ctl_init - main entry point for ctl.
  *
  */
 void
-mpt3sas_ctl_init(void)
+mpt3sas_ctl_init(ushort hbas_to_enumerate)
 {
        async_queue = NULL;
-       if (misc_register(&ctl_dev) < 0)
-               pr_err("%s can't register misc device [minor=%d]\n",
-                   MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
+
+       /* Don't register mpt3ctl ioctl device if
+        * hbas_to_enumarate is one.
+        */
+       if (hbas_to_enumerate != 1)
+               if (misc_register(&ctl_dev) < 0)
+                       pr_err("%s can't register misc device [minor=%d]\n",
+                           MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR);
+
+       /* Don't register mpt3ctl ioctl device if
+        * hbas_to_enumarate is two.
+        */
+       if (hbas_to_enumerate != 2)
+               if (misc_register(&gen2_ctl_dev) < 0)
+                       pr_err("%s can't register misc device [minor=%d]\n",
+                           MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
 
        init_waitqueue_head(&ctl_poll_wait);
 }
@@ -3254,7 +3432,7 @@ mpt3sas_ctl_init(void)
  *
  */
 void
-mpt3sas_ctl_exit(void)
+mpt3sas_ctl_exit(ushort hbas_to_enumerate)
 {
        struct MPT3SAS_ADAPTER *ioc;
        int i;
@@ -3279,5 +3457,8 @@ mpt3sas_ctl_exit(void)
 
                kfree(ioc->event_log);
        }
-       misc_deregister(&ctl_dev);
+       if (hbas_to_enumerate != 1)
+               misc_deregister(&ctl_dev);
+       if (hbas_to_enumerate != 2)
+               misc_deregister(&gen2_ctl_dev);
 }
index aee99ce67e54ec8355e51eedf98039a4488d399e..89408356d252432b4d57f9ae3964ec4d1381b14a 100644 (file)
 #include <linux/miscdevice.h>
 #endif
 
-
+#ifndef MPT2SAS_MINOR
+#define MPT2SAS_MINOR          (MPT_MINOR + 1)
+#endif
 #ifndef MPT3SAS_MINOR
 #define MPT3SAS_MINOR          (MPT_MINOR + 2)
 #endif
+#define MPT2SAS_DEV_NAME       "mpt2ctl"
 #define MPT3SAS_DEV_NAME       "mpt3ctl"
 #define MPT3_MAGIC_NUMBER      'L'
 #define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
@@ -138,6 +141,7 @@ struct mpt3_ioctl_pci_info {
 #define MPT2_IOCTL_INTERFACE_FC_IP     (0x02)
 #define MPT2_IOCTL_INTERFACE_SAS       (0x03)
 #define MPT2_IOCTL_INTERFACE_SAS2      (0x04)
+#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200      (0x05)
 #define MPT3_IOCTL_INTERFACE_SAS3      (0x06)
 #define MPT2_IOCTL_VERSION_LENGTH      (32)
 
index 4e8a63fdb304f9c2c732b95cf8e89f48d5783f31..cceeb2c16e64c6e13d1cd8ae5c163b51af972086 100644 (file)
 #define MPT_DEBUG_TRIGGER_DIAG         0x00200000
 
 
-/*
- * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig
- */
-
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 #define MPT_CHECK_LOGGING(IOC, CMD, BITS)                      \
 {                                                              \
        if (IOC->logging_level & BITS)                          \
                CMD;                                            \
 }
-#else
-#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
-#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
-
 
 /*
  * debug macros
 
 
 /* inline functions for dumping debug data*/
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
+
 /**
  * _debug_dump_mf - print message frame contents
  * @mpi_request: pointer to message frame
@@ -211,10 +202,5 @@ _debug_dump_config(void *mpi_request, int sz)
        }
        pr_info("\n");
 }
-#else
-#define _debug_dump_mf(mpi_request, sz)
-#define _debug_dump_reply(mpi_request, sz)
-#define _debug_dump_config(mpi_request, sz)
-#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */
 
 #endif /* MPT3SAS_DEBUG_H_INCLUDED */
index 8ccef38523fa46c823672878978e1ab8d022018a..d95206b7e1167861531d2cd29c9ef27e7da82c25 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/raid_class.h>
+#include <asm/unaligned.h>
 
 #include "mpt3sas_base.h"
 
-MODULE_AUTHOR(MPT3SAS_AUTHOR);
-MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
-
 #define RAID_CHANNEL 1
 /* forward proto's */
 static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
@@ -75,11 +71,16 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
 
 static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
 
-static void _scsih_scan_start(struct Scsi_Host *shost);
-static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time);
-
 /* global parameters */
 LIST_HEAD(mpt3sas_ioc_list);
+/* global ioc lock for list operations */
+DEFINE_SPINLOCK(gioc_lock);
+
+MODULE_AUTHOR(MPT3SAS_AUTHOR);
+MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
+MODULE_ALIAS("mpt2sas");
 
 /* local parameters */
 static u8 scsi_io_cb_idx = -1;
@@ -90,7 +91,8 @@ static u8 port_enable_cb_idx = -1;
 static u8 transport_cb_idx = -1;
 static u8 scsih_cb_idx = -1;
 static u8 config_cb_idx = -1;
-static int mpt_ids;
+static int mpt2_ids;
+static int mpt3_ids;
 
 static u8 tm_tr_cb_idx = -1 ;
 static u8 tm_tr_volume_cb_idx = -1 ;
@@ -117,8 +119,12 @@ static u64 max_lun = MPT3SAS_MAX_LUN;
 module_param(max_lun, ullong, 0);
 MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
 
-
-
+static ushort hbas_to_enumerate;
+module_param(hbas_to_enumerate, ushort, 0);
+MODULE_PARM_DESC(hbas_to_enumerate,
+               " 0 - enumerates both SAS 2.0 & SAS 3.0 generation HBAs\n \
+                 1 - enumerates only SAS 2.0 generation HBAs\n \
+                 2 - enumerates only SAS 3.0 generation HBAs (default=0)");
 
 /* diag_buffer_enable is bitwise
  * bit 0 set = TRACE
@@ -143,8 +149,8 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
 
 
 /* raid transport support */
-
-static struct raid_template *mpt3sas_raid_template;
+struct raid_template *mpt3sas_raid_template;
+struct raid_template *mpt2sas_raid_template;
 
 
 /**
@@ -191,11 +197,36 @@ struct fw_event_work {
        u8                      VP_ID;
        u8                      ignore;
        u16                     event;
+       struct kref             refcount;
        char                    event_data[0] __aligned(4);
 };
 
-/* raid transport support */
-static struct raid_template *mpt3sas_raid_template;
+static void fw_event_work_free(struct kref *r)
+{
+       kfree(container_of(r, struct fw_event_work, refcount));
+}
+
+static void fw_event_work_get(struct fw_event_work *fw_work)
+{
+       kref_get(&fw_work->refcount);
+}
+
+static void fw_event_work_put(struct fw_event_work *fw_work)
+{
+       kref_put(&fw_work->refcount, fw_event_work_free);
+}
+
+static struct fw_event_work *alloc_fw_event_work(int len)
+{
+       struct fw_event_work *fw_event;
+
+       fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
+       if (!fw_event)
+               return NULL;
+
+       kref_init(&fw_event->refcount);
+       return fw_event;
+}
 
 /**
  * struct _scsi_io_transfer - scsi io transfer
@@ -245,28 +276,6 @@ struct _scsi_io_transfer {
        u32     transfer_length;
 };
 
-/*
- * The pci device ids are defined in mpi/mpi2_cnfg.h.
- */
-static const struct pci_device_id scsih_pci_table[] = {
-       /* Fury ~ 3004 and 3008 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
-               PCI_ANY_ID, PCI_ANY_ID },
-       /* Invader ~ 3108 */
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
-               PCI_ANY_ID, PCI_ANY_ID },
-       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
-               PCI_ANY_ID, PCI_ANY_ID },
-       {0}     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, scsih_pci_table);
-
 /**
  * _scsih_set_debug_level - global setting of ioc->logging_level.
  *
@@ -282,8 +291,10 @@ _scsih_set_debug_level(const char *val, struct kernel_param *kp)
                return ret;
 
        pr_info("setting logging_level(0x%08x)\n", logging_level);
+       spin_lock(&gioc_lock);
        list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
                ioc->logging_level = logging_level;
+       spin_unlock(&gioc_lock);
        return 0;
 }
 module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
@@ -518,8 +529,61 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
        }
 }
 
+static struct _sas_device *
+__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
+               struct MPT3SAS_TARGET *tgt_priv)
+{
+       struct _sas_device *ret;
+
+       assert_spin_locked(&ioc->sas_device_lock);
+
+       ret = tgt_priv->sdev;
+       if (ret)
+               sas_device_get(ret);
+
+       return ret;
+}
+
+static struct _sas_device *
+mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
+               struct MPT3SAS_TARGET *tgt_priv)
+{
+       struct _sas_device *ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       return ret;
+}
+
+
+struct _sas_device *
+__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
+                                       u64 sas_address)
+{
+       struct _sas_device *sas_device;
+
+       assert_spin_locked(&ioc->sas_device_lock);
+
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
+               if (sas_device->sas_address == sas_address)
+                       goto found_device;
+
+       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
+               if (sas_device->sas_address == sas_address)
+                       goto found_device;
+
+       return NULL;
+
+found_device:
+       sas_device_get(sas_device);
+       return sas_device;
+}
+
 /**
- * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search
+ * mpt3sas_get_sdev_by_addr - sas device search
  * @ioc: per adapter object
  * @sas_address: sas address
  * Context: Calling function should acquire ioc->sas_device_lock
@@ -528,24 +592,44 @@ _scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
  * object.
  */
 struct _sas_device *
-mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
+mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
        u64 sas_address)
+{
+       struct _sas_device *sas_device;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
+                       sas_address);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       return sas_device;
+}
+
+static struct _sas_device *
+__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct _sas_device *sas_device;
 
+       assert_spin_locked(&ioc->sas_device_lock);
+
        list_for_each_entry(sas_device, &ioc->sas_device_list, list)
-               if (sas_device->sas_address == sas_address)
-                       return sas_device;
+               if (sas_device->handle == handle)
+                       goto found_device;
 
        list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
-               if (sas_device->sas_address == sas_address)
-                       return sas_device;
+               if (sas_device->handle == handle)
+                       goto found_device;
 
        return NULL;
+
+found_device:
+       sas_device_get(sas_device);
+       return sas_device;
 }
 
 /**
- * _scsih_sas_device_find_by_handle - sas device search
+ * mpt3sas_get_sdev_by_handle - sas device search
  * @ioc: per adapter object
  * @handle: sas device handle (assigned by firmware)
  * Context: Calling function should acquire ioc->sas_device_lock
@@ -554,19 +638,16 @@ mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
  * object.
  */
 static struct _sas_device *
-_scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct _sas_device *sas_device;
+       unsigned long flags;
 
-       list_for_each_entry(sas_device, &ioc->sas_device_list, list)
-               if (sas_device->handle == handle)
-                       return sas_device;
-
-       list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
-               if (sas_device->handle == handle)
-                       return sas_device;
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
-       return NULL;
+       return sas_device;
 }
 
 /**
@@ -575,7 +656,7 @@ _scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
  * @sas_device: the sas_device object
  * Context: This function will acquire ioc->sas_device_lock.
  *
- * Removing object and freeing associated memory from the ioc->sas_device_list.
+ * If sas_device is on the list, remove it and decrement its reference count.
  */
 static void
 _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
@@ -602,9 +683,15 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
                   ioc->name, sas_device->enclosure_level,
                   sas_device->connector_name);
 
+       /*
+        * The lock serializes access to the list, but we still need to verify
+        * that nobody removed the entry while we were waiting on the lock.
+        */
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       list_del(&sas_device->list);
-       kfree(sas_device);
+       if (!list_empty(&sas_device->list)) {
+               list_del_init(&sas_device->list);
+               sas_device_put(sas_device);
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 }
 
@@ -625,12 +712,16 @@ _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                return;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
-       if (sas_device)
-               list_del(&sas_device->list);
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+       if (sas_device) {
+               list_del_init(&sas_device->list);
+               sas_device_put(sas_device);
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (sas_device)
+       if (sas_device) {
                _scsih_remove_device(ioc, sas_device);
+               sas_device_put(sas_device);
+       }
 }
 
 /**
@@ -651,13 +742,16 @@ mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
                return;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-           sas_address);
-       if (sas_device)
-               list_del(&sas_device->list);
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
+       if (sas_device) {
+               list_del_init(&sas_device->list);
+               sas_device_put(sas_device);
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (sas_device)
+       if (sas_device) {
                _scsih_remove_device(ioc, sas_device);
+               sas_device_put(sas_device);
+       }
 }
 
 /**
@@ -692,6 +786,7 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
                    sas_device->enclosure_level, sas_device->connector_name));
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device_get(sas_device);
        list_add_tail(&sas_device->list, &ioc->sas_device_list);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
@@ -745,6 +840,7 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
                    sas_device->connector_name));
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       sas_device_get(sas_device);
        list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
        _scsih_determine_boot_device(ioc, sas_device, 0);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -778,7 +874,7 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
 }
 
 /**
- * _scsih_raid_device_find_by_handle - raid device search
+ * mpt3sas_raid_device_find_by_handle - raid device search
  * @ioc: per adapter object
  * @handle: sas device handle (assigned by firmware)
  * Context: Calling function should acquire ioc->raid_device_lock
@@ -786,8 +882,8 @@ _scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
  * This searches for raid_device based on handle, then return raid_device
  * object.
  */
-static struct _raid_device *
-_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+struct _raid_device *
+mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct _raid_device *raid_device, *r;
 
@@ -1095,14 +1191,14 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
 }
 
 /**
- * _scsih_change_queue_depth - setting device queue depth
+ * scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
  *
  * Returns queue depth.
  */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int
+scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct Scsi_Host *shost = sdev->host;
        int max_depth;
@@ -1123,12 +1219,15 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
                goto not_sata;
        if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
                goto not_sata;
+
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-          sas_device_priv_data->sas_target->sas_address);
-       if (sas_device && sas_device->device_info &
-           MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
-               max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
+       sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
+       if (sas_device) {
+               if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+                       max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
+
+               sas_device_put(sas_device);
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
  not_sata:
@@ -1141,14 +1240,14 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 }
 
 /**
- * _scsih_target_alloc - target add routine
+ * scsih_target_alloc - target add routine
  * @starget: scsi target struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_target_alloc(struct scsi_target *starget)
+int
+scsih_target_alloc(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1176,7 +1275,9 @@ _scsih_target_alloc(struct scsi_target *starget)
                        sas_target_priv_data->handle = raid_device->handle;
                        sas_target_priv_data->sas_address = raid_device->wwid;
                        sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
-                       raid_device->starget = starget;
+                       sas_target_priv_data->raid_device = raid_device;
+                       if (ioc->is_warpdrive)
+                               raid_device->starget = starget;
                }
                spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
                return 0;
@@ -1185,12 +1286,13 @@ _scsih_target_alloc(struct scsi_target *starget)
        /* sas/sata devices */
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        rphy = dev_to_rphy(starget->dev.parent);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
           rphy->identify.sas_address);
 
        if (sas_device) {
                sas_target_priv_data->handle = sas_device->handle;
                sas_target_priv_data->sas_address = sas_device->sas_address;
+               sas_target_priv_data->sdev = sas_device;
                sas_device->starget = starget;
                sas_device->id = starget->id;
                sas_device->channel = starget->channel;
@@ -1206,13 +1308,13 @@ _scsih_target_alloc(struct scsi_target *starget)
 }
 
 /**
- * _scsih_target_destroy - target destroy routine
+ * scsih_target_destroy - target destroy routine
  * @starget: scsi target struct
  *
  * Returns nothing.
  */
-static void
-_scsih_target_destroy(struct scsi_target *starget)
+void
+scsih_target_destroy(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(&starget->dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1240,13 +1342,21 @@ _scsih_target_destroy(struct scsi_target *starget)
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        rphy = dev_to_rphy(starget->dev.parent);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-          rphy->identify.sas_address);
+       sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
        if (sas_device && (sas_device->starget == starget) &&
            (sas_device->id == starget->id) &&
            (sas_device->channel == starget->channel))
                sas_device->starget = NULL;
 
+       if (sas_device) {
+               /*
+                * Corresponding get() is in _scsih_target_alloc()
+                */
+               sas_target_priv_data->sdev = NULL;
+               sas_device_put(sas_device);
+
+               sas_device_put(sas_device);
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
  out:
@@ -1255,14 +1365,14 @@ _scsih_target_destroy(struct scsi_target *starget)
 }
 
 /**
- * _scsih_slave_alloc - device add routine
+ * scsih_slave_alloc - device add routine
  * @sdev: scsi device struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_slave_alloc(struct scsi_device *sdev)
+int
+scsih_slave_alloc(struct scsi_device *sdev)
 {
        struct Scsi_Host *shost;
        struct MPT3SAS_ADAPTER *ioc;
@@ -1302,14 +1412,18 @@ _scsih_slave_alloc(struct scsi_device *sdev)
 
        if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
                spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+               sas_device = __mpt3sas_get_sdev_by_addr(ioc,
                                        sas_target_priv_data->sas_address);
                if (sas_device && (sas_device->starget == NULL)) {
                        sdev_printk(KERN_INFO, sdev,
                        "%s : sas_device->starget set to starget @ %d\n",
-                               __func__, __LINE__);
+                            __func__, __LINE__);
                        sas_device->starget = starget;
                }
+
+               if (sas_device)
+                       sas_device_put(sas_device);
+
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 
@@ -1317,13 +1431,13 @@ _scsih_slave_alloc(struct scsi_device *sdev)
 }
 
 /**
- * _scsih_slave_destroy - device destroy routine
+ * scsih_slave_destroy - device destroy routine
  * @sdev: scsi device struct
  *
  * Returns nothing.
  */
-static void
-_scsih_slave_destroy(struct scsi_device *sdev)
+void
+scsih_slave_destroy(struct scsi_device *sdev)
 {
        struct MPT3SAS_TARGET *sas_target_priv_data;
        struct scsi_target *starget;
@@ -1344,10 +1458,13 @@ _scsih_slave_destroy(struct scsi_device *sdev)
 
        if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
                spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-                  sas_target_priv_data->sas_address);
+               sas_device = __mpt3sas_get_sdev_from_target(ioc,
+                               sas_target_priv_data);
                if (sas_device && !sas_target_priv_data->num_luns)
                        sas_device->starget = NULL;
+
+               if (sas_device)
+                       sas_device_put(sas_device);
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 
@@ -1409,23 +1526,26 @@ _scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
  */
 
 /**
- * _scsih_is_raid - return boolean indicating device is raid volume
+ * scsih_is_raid - return boolean indicating device is raid volume
  * @dev the device struct object
  */
-static int
-_scsih_is_raid(struct device *dev)
+int
+scsih_is_raid(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
+       struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
 
+       if (ioc->is_warpdrive)
+               return 0;
        return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
 }
 
 /**
- * _scsih_get_resync - get raid volume resync percent complete
+ * scsih_get_resync - get raid volume resync percent complete
  * @dev the device struct object
  */
-static void
-_scsih_get_resync(struct device *dev)
+void
+scsih_get_resync(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1439,6 +1559,9 @@ _scsih_get_resync(struct device *dev)
 
        percent_complete = 0;
        handle = 0;
+       if (ioc->is_warpdrive)
+               goto out;
+
        spin_lock_irqsave(&ioc->raid_device_lock, flags);
        raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
            sdev->channel);
@@ -1466,15 +1589,18 @@ _scsih_get_resync(struct device *dev)
                percent_complete = 0;
 
  out:
-       raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
+       if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+               raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
+       if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+               raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
 }
 
 /**
- * _scsih_get_state - get raid volume level
+ * scsih_get_state - get raid volume level
  * @dev the device struct object
  */
-static void
-_scsih_get_state(struct device *dev)
+void
+scsih_get_state(struct device *dev)
 {
        struct scsi_device *sdev = to_scsi_device(dev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
@@ -1524,7 +1650,10 @@ _scsih_get_state(struct device *dev)
                break;
        }
  out:
-       raid_set_state(mpt3sas_raid_template, dev, state);
+       if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+               raid_set_state(mpt2sas_raid_template, dev, state);
+       if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+               raid_set_state(mpt3sas_raid_template, dev, state);
 }
 
 /**
@@ -1533,7 +1662,8 @@ _scsih_get_state(struct device *dev)
  * @volume_type: volume type
  */
 static void
-_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
+_scsih_set_level(struct MPT3SAS_ADAPTER *ioc,
+       struct scsi_device *sdev, u8 volume_type)
 {
        enum raid_level level = RAID_LEVEL_UNKNOWN;
 
@@ -1552,7 +1682,12 @@ _scsih_set_level(struct scsi_device *sdev, u8 volume_type)
                break;
        }
 
-       raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
+       if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+               raid_set_level(mpt2sas_raid_template,
+                              &sdev->sdev_gendev, level);
+       if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
+               raid_set_level(mpt3sas_raid_template,
+                              &sdev->sdev_gendev, level);
 }
 
 
@@ -1622,8 +1757,6 @@ _scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
        return 0;
 }
 
-
-
 /**
  * _scsih_enable_tlr - setting TLR flags
  * @ioc: per adapter object
@@ -1652,14 +1785,14 @@ _scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
 }
 
 /**
- * _scsih_slave_configure - device configure routine.
+ * scsih_slave_configure - device configure routine.
  * @sdev: scsi device struct
  *
  * Returns 0 if ok. Any other return is assumed to be an error and
  * the device is ignored.
  */
-static int
-_scsih_slave_configure(struct scsi_device *sdev)
+int
+scsih_slave_configure(struct scsi_device *sdev)
 {
        struct Scsi_Host *shost = sdev->host;
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -1686,7 +1819,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
        if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
 
                spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
                spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
                if (!raid_device) {
                        dfailprintk(ioc, pr_warn(MPT3SAS_FMT
@@ -1702,6 +1835,10 @@ _scsih_slave_configure(struct scsi_device *sdev)
                        return 1;
                }
 
+               /*
+                * WARPDRIVE: Initialize the required data for Direct IO
+                */
+               mpt3sas_init_warpdrive_properties(ioc, raid_device);
 
                /* RAID Queue Depth Support
                 * IS volume = underlying qdepth of drive type, either
@@ -1750,17 +1887,19 @@ _scsih_slave_configure(struct scsi_device *sdev)
                        break;
                }
 
-               sdev_printk(KERN_INFO, sdev,
-                       "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
-                        r_level, raid_device->handle,
-                        (unsigned long long)raid_device->wwid,
-                        raid_device->num_pds, ds);
-
+               if (!ioc->hide_ir_msg)
+                       sdev_printk(KERN_INFO, sdev,
+                          "%s: handle(0x%04x), wwid(0x%016llx),"
+                           " pd_count(%d), type(%s)\n",
+                           r_level, raid_device->handle,
+                           (unsigned long long)raid_device->wwid,
+                           raid_device->num_pds, ds);
 
-               _scsih_change_queue_depth(sdev, qdepth);
+               scsih_change_queue_depth(sdev, qdepth);
 
-/* raid transport support */
-               _scsih_set_level(sdev, raid_device->volume_type);
+               /* raid transport support */
+               if (!ioc->is_warpdrive)
+                       _scsih_set_level(ioc, sdev, raid_device->volume_type);
                return 0;
        }
 
@@ -1783,7 +1922,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
        }
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
           sas_device_priv_data->sas_target->sas_address);
        if (!sas_device) {
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
@@ -1823,13 +1962,14 @@ _scsih_slave_configure(struct scsi_device *sdev)
                     ds, sas_device->enclosure_level,
                     sas_device->connector_name);
 
+       sas_device_put(sas_device);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
        if (!ssp_target)
                _scsih_display_sata_capabilities(ioc, handle, sdev);
 
 
-       _scsih_change_queue_depth(sdev, qdepth);
+       scsih_change_queue_depth(sdev, qdepth);
 
        if (ssp_target) {
                sas_read_port_mode_page(sdev);
@@ -1840,7 +1980,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
 }
 
 /**
- * _scsih_bios_param - fetch head, sector, cylinder info for a disk
+ * scsih_bios_param - fetch head, sector, cylinder info for a disk
  * @sdev: scsi device struct
  * @bdev: pointer to block device context
  * @capacity: device size (in 512 byte sectors)
@@ -1851,8 +1991,8 @@ _scsih_slave_configure(struct scsi_device *sdev)
  *
  * Return nothing.
  */
-static int
-_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+int
+scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
        sector_t capacity, int params[])
 {
        int             heads;
@@ -2209,7 +2349,10 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
 
        if (!priv_target)
                return;
-       device_str = "volume";
+       if (ioc->hide_ir_msg)
+               device_str = "WarpDrive";
+       else
+               device_str = "volume";
 
        scsi_print_command(scmd);
        if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
@@ -2219,8 +2362,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
                    device_str, (unsigned long long)priv_target->sas_address);
        } else {
                spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-                   priv_target->sas_address);
+               sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
                if (sas_device) {
                        if (priv_target->flags &
                            MPT_TARGET_FLAGS_RAID_COMPONENT) {
@@ -2246,19 +2388,21 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
                                "enclosure level(0x%04x),connector name(%s)\n",
                                 sas_device->enclosure_level,
                                 sas_device->connector_name);
+
+                       sas_device_put(sas_device);
                }
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 }
 
 /**
- * _scsih_abort - eh threads main abort routine
+ * scsih_abort - eh threads main abort routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_abort(struct scsi_cmnd *scmd)
+int
+scsih_abort(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
@@ -2311,21 +2455,23 @@ _scsih_abort(struct scsi_cmnd *scmd)
 }
 
 /**
- * _scsih_dev_reset - eh threads main device reset routine
+ * scsih_dev_reset - eh threads main device reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_dev_reset(struct scsi_cmnd *scmd)
+int
+scsih_dev_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
-       struct _sas_device *sas_device;
-       unsigned long flags;
+       struct _sas_device *sas_device = NULL;
        u16     handle;
        int r;
 
+       struct scsi_target *starget = scmd->device->sdev_target;
+       struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
+
        sdev_printk(KERN_INFO, scmd->device,
                "attempting device reset! scmd(%p)\n", scmd);
        _scsih_tm_display_info(ioc, scmd);
@@ -2344,12 +2490,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
        handle = 0;
        if (sas_device_priv_data->sas_target->flags &
            MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = _scsih_sas_device_find_by_handle(ioc,
-                  sas_device_priv_data->sas_target->handle);
+               sas_device = mpt3sas_get_sdev_from_target(ioc,
+                               target_priv_data);
                if (sas_device)
                        handle = sas_device->volume_handle;
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        } else
                handle = sas_device_priv_data->sas_target->handle;
 
@@ -2366,25 +2510,29 @@ _scsih_dev_reset(struct scsi_cmnd *scmd)
  out:
        sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
            ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+       if (sas_device)
+               sas_device_put(sas_device);
+
        return r;
 }
 
 /**
- * _scsih_target_reset - eh threads main target reset routine
+ * scsih_target_reset - eh threads main target reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_target_reset(struct scsi_cmnd *scmd)
+int
+scsih_target_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
-       struct _sas_device *sas_device;
-       unsigned long flags;
+       struct _sas_device *sas_device = NULL;
        u16     handle;
        int r;
        struct scsi_target *starget = scmd->device->sdev_target;
+       struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
 
        starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
                scmd);
@@ -2404,12 +2552,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
        handle = 0;
        if (sas_device_priv_data->sas_target->flags &
            MPT_TARGET_FLAGS_RAID_COMPONENT) {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = _scsih_sas_device_find_by_handle(ioc,
-                  sas_device_priv_data->sas_target->handle);
+               sas_device = mpt3sas_get_sdev_from_target(ioc,
+                               target_priv_data);
                if (sas_device)
                        handle = sas_device->volume_handle;
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        } else
                handle = sas_device_priv_data->sas_target->handle;
 
@@ -2426,18 +2572,22 @@ _scsih_target_reset(struct scsi_cmnd *scmd)
  out:
        starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
            ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+       if (sas_device)
+               sas_device_put(sas_device);
+
        return r;
 }
 
 
 /**
- * _scsih_host_reset - eh threads main host reset routine
+ * scsih_host_reset - eh threads main host reset routine
  * @scmd: pointer to scsi command object
  *
  * Returns SUCCESS if command aborted else FAILED
  */
-static int
-_scsih_host_reset(struct scsi_cmnd *scmd)
+int
+scsih_host_reset(struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
        int r, retval;
@@ -2483,32 +2633,36 @@ _scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
                return;
 
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       fw_event_work_get(fw_event);
        INIT_LIST_HEAD(&fw_event->list);
        list_add_tail(&fw_event->list, &ioc->fw_event_list);
        INIT_WORK(&fw_event->work, _firmware_event_work);
+       fw_event_work_get(fw_event);
        queue_work(ioc->firmware_event_thread, &fw_event->work);
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
 /**
- * _scsih_fw_event_free - delete fw_event
+ * _scsih_fw_event_del_from_list - delete fw_event from the list
  * @ioc: per adapter object
  * @fw_event: object describing the event
  * Context: This function will acquire ioc->fw_event_lock.
  *
- * This removes firmware event object from link list, frees associated memory.
+ * If the fw_event is on the fw_event_list, remove it and do a put.
  *
  * Return nothing.
  */
 static void
-_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
+_scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
        *fw_event)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
-       list_del(&fw_event->list);
-       kfree(fw_event);
+       if (!list_empty(&fw_event->list)) {
+               list_del_init(&fw_event->list);
+               fw_event_work_put(fw_event);
+       }
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
@@ -2525,17 +2679,19 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
        struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
 {
        struct fw_event_work *fw_event;
+       u16 sz;
 
        if (ioc->is_driver_loading)
                return;
-       fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data),
-                          GFP_ATOMIC);
+       sz = sizeof(*event_data);
+       fw_event = alloc_fw_event_work(sz);
        if (!fw_event)
                return;
        fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
        fw_event->ioc = ioc;
        memcpy(fw_event->event_data, event_data, sizeof(*event_data));
        _scsih_fw_event_add(ioc, fw_event);
+       fw_event_work_put(fw_event);
 }
 
 /**
@@ -2551,12 +2707,13 @@ _scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
 
        if (ioc->is_driver_loading)
                return;
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       fw_event = alloc_fw_event_work(0);
        if (!fw_event)
                return;
        fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
+       fw_event_work_put(fw_event);
 }
 
 /**
@@ -2570,12 +2727,29 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
 {
        struct fw_event_work *fw_event;
 
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       fw_event = alloc_fw_event_work(0);
        if (!fw_event)
                return;
        fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
+       fw_event_work_put(fw_event);
+}
+
+static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
+{
+       unsigned long flags;
+       struct fw_event_work *fw_event = NULL;
+
+       spin_lock_irqsave(&ioc->fw_event_lock, flags);
+       if (!list_empty(&ioc->fw_event_list)) {
+               fw_event = list_first_entry(&ioc->fw_event_list,
+                               struct fw_event_work, list);
+               list_del_init(&fw_event->list);
+       }
+       spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
+       return fw_event;
 }
 
 /**
@@ -2590,17 +2764,25 @@ mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
 static void
 _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
 {
-       struct fw_event_work *fw_event, *next;
+       struct fw_event_work *fw_event;
 
        if (list_empty(&ioc->fw_event_list) ||
             !ioc->firmware_event_thread || in_interrupt())
                return;
 
-       list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
-               if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
-                       _scsih_fw_event_free(ioc, fw_event);
-                       continue;
-               }
+       while ((fw_event = dequeue_next_fw_event(ioc))) {
+               /*
+                * Wait on the fw_event to complete. If this returns 1, then
+                * the event was never executed, and we need a put for the
+                * reference the delayed_work had on the fw_event.
+                *
+                * If it did execute, we wait for it to finish, and the put will
+                * happen from _firmware_event_work()
+                */
+               if (cancel_delayed_work_sync(&fw_event->delayed_work))
+                       fw_event_work_put(fw_event);
+
+               fw_event_work_put(fw_event);
        }
 }
 
@@ -2763,7 +2945,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        struct scsi_device *sdev;
        struct _sas_device *sas_device;
 
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
        if (!sas_device)
                return;
 
@@ -2779,6 +2961,8 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                        continue;
                _scsih_internal_device_block(sdev, sas_device_priv_data);
        }
+
+       sas_device_put(sas_device);
 }
 
 /**
@@ -2807,12 +2991,13 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
                if (mpt3sas_port->remote_identify.device_type ==
                    SAS_END_DEVICE) {
                        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-                       sas_device =
-                           mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-                          mpt3sas_port->remote_identify.sas_address);
-                       if (sas_device)
+                       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
+                           mpt3sas_port->remote_identify.sas_address);
+                       if (sas_device) {
                                set_bit(sas_device->handle,
-                                   ioc->blocking_handles);
+                                               ioc->blocking_handles);
+                               sas_device_put(sas_device);
+                       }
                        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
                }
        }
@@ -2880,7 +3065,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        Mpi2SCSITaskManagementRequest_t *mpi_request;
        u16 smid;
-       struct _sas_device *sas_device;
+       struct _sas_device *sas_device = NULL;
        struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
        u64 sas_address = 0;
        unsigned long flags;
@@ -2913,7 +3098,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                return;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
        if (sas_device && sas_device->starget &&
            sas_device->starget->hostdata) {
                sas_target_priv_data = sas_device->starget->hostdata;
@@ -2947,14 +3132,14 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        if (!smid) {
                delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
                if (!delayed_tr)
-                       return;
+                       goto out;
                INIT_LIST_HEAD(&delayed_tr->list);
                delayed_tr->handle = handle;
                list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
                dewtprintk(ioc, pr_info(MPT3SAS_FMT
                    "DELAYED:tr:handle(0x%04x), (open)\n",
                    ioc->name, handle));
-               return;
+               goto out;
        }
 
        dewtprintk(ioc, pr_info(MPT3SAS_FMT
@@ -2968,6 +3153,10 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
        mpt3sas_base_put_smid_hi_priority(ioc, smid);
        mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
+
+out:
+       if (sas_device)
+               sas_device_put(sas_device);
 }
 
 /**
@@ -3337,7 +3526,7 @@ _scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        unsigned long flags;
 
        spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+       raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
        if (raid_device && raid_device->starget &&
            raid_device->starget->hostdata) {
                sas_target_priv_data =
@@ -3398,6 +3587,9 @@ _scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
        a = 0;
        b = 0;
 
+       if (ioc->is_warpdrive)
+               return;
+
        /* Volume Resets for Deleted or Removed */
        element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
        for (i = 0; i < event_data->NumElements; i++, element++) {
@@ -3634,8 +3826,9 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
 }
 
 
+
 /**
- * _scsih_qcmd - main scsi request entry point
+ * scsih_qcmd - main scsi request entry point
  * @scmd: pointer to scsi command object
  * @done: function pointer to be invoked on completion
  *
@@ -3645,21 +3838,20 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
  * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
  * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
  */
-static int
-_scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+int
+scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct _raid_device *raid_device;
        Mpi2SCSIIORequest_t *mpi_request;
        u32 mpi_control;
        u16 smid;
        u16 handle;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_SCSI)
                scsi_print_command(scmd);
-#endif
 
        sas_device_priv_data = scmd->device->hostdata;
        if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
@@ -3709,7 +3901,11 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        /* set tags */
        mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
 
-       if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
+       /* Make sure Device is not raid volume.
+        * We do not expose raid functionality to upper layer for warpdrive.
+        */
+       if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
+           && (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
            scmd->cmd_len != 32)
                mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
 
@@ -3752,13 +3948,19 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        } else
                ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
 
+       raid_device = sas_target_priv_data->raid_device;
+       if (raid_device && raid_device->direct_io_enabled)
+               mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request,
+                   smid);
+
        if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
                if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
                        mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
                            MPI25_SCSIIO_IOFLAGS_FAST_PATH);
                        mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
                } else
-                       mpt3sas_base_put_smid_scsi_io(ioc, smid, handle);
+                       mpt3sas_base_put_smid_scsi_io(ioc, smid,
+                           le16_to_cpu(mpi_request->DevHandle));
        } else
                mpt3sas_base_put_smid_default(ioc, smid);
        return 0;
@@ -3790,7 +3992,6 @@ _scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
        }
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
  * @ioc: per adapter object
@@ -3818,14 +4019,16 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
        char *desc_scsi_state = ioc->tmp_string;
        u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
        struct _sas_device *sas_device = NULL;
-       unsigned long flags;
        struct scsi_target *starget = scmd->device->sdev_target;
        struct MPT3SAS_TARGET *priv_target = starget->hostdata;
        char *device_str = NULL;
 
        if (!priv_target)
                return;
-       device_str = "volume";
+       if (ioc->hide_ir_msg)
+               device_str = "WarpDrive";
+       else
+               device_str = "volume";
 
        if (log_info == 0x31170000)
                return;
@@ -3946,9 +4149,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
                pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
                    device_str, (unsigned long long)priv_target->sas_address);
        } else {
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-                   priv_target->sas_address);
+               sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
                if (sas_device) {
                        pr_warn(MPT3SAS_FMT
                                "\tsas_address(0x%016llx), phy(%d)\n",
@@ -3967,8 +4168,9 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
                                  " connector name( %s)\n", ioc->name,
                                  sas_device->enclosure_level,
                                  sas_device->connector_name);
+
+                       sas_device_put(sas_device);
                }
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        }
 
        pr_warn(MPT3SAS_FMT
@@ -4003,7 +4205,6 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
                _scsih_response_code(ioc, response_bytes[0]);
        }
 }
-#endif
 
 /**
  * _scsih_turn_on_pfa_led - illuminate PFA LED
@@ -4020,7 +4221,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        Mpi2SepRequest_t mpi_request;
        struct _sas_device *sas_device;
 
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
        if (!sas_device)
                return;
 
@@ -4035,7 +4236,7 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
            &mpi_request)) != 0) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
                __FILE__, __LINE__, __func__);
-               return;
+               goto out;
        }
        sas_device->pfa_led_on = 1;
 
@@ -4044,9 +4245,12 @@ _scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                        "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
                        ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
                    le32_to_cpu(mpi_reply.IOCLogInfo)));
-               return;
+               goto out;
        }
+out:
+       sas_device_put(sas_device);
 }
+
 /**
  * _scsih_turn_off_pfa_led - turn off Fault LED
  * @ioc: per adapter object
@@ -4085,6 +4289,7 @@ _scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
                return;
        }
 }
+
 /**
  * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
  * @ioc: per adapter object
@@ -4098,13 +4303,14 @@ _scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct fw_event_work *fw_event;
 
-       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       fw_event = alloc_fw_event_work(0);
        if (!fw_event)
                return;
        fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
        fw_event->device_handle = handle;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
+       fw_event_work_put(fw_event);
 }
 
 /**
@@ -4128,19 +4334,17 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 
        /* only handle non-raid devices */
        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);
-               return;
-       }
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
+       if (!sas_device)
+               goto out_unlock;
+
        starget = sas_device->starget;
        sas_target_priv_data = starget->hostdata;
 
        if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
-          ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
-       }
+          ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
+               goto out_unlock;
+
        if (sas_device->enclosure_handle != 0)
                starget_printk(KERN_INFO, starget, "predicted fault, "
                        "enclosure logical id(0x%016llx), slot(%d)\n",
@@ -4163,7 +4367,7 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        if (!event_reply) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
-               return;
+               goto out;
        }
 
        event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
@@ -4180,6 +4384,14 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
        mpt3sas_ctl_add_to_event_log(ioc, event_reply);
        kfree(event_reply);
+out:
+       if (sas_device)
+               sas_device_put(sas_device);
+       return;
+
+out_unlock:
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       goto out;
 }
 
 /**
@@ -4207,6 +4419,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        u32 log_info;
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
+       unsigned long flags;
 
        mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
        scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
@@ -4228,6 +4441,24 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        }
        ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
 
+       /*
+        * WARPDRIVE: If direct_io is set then it is directIO,
+        * the failed direct I/O should be redirected to volume
+        */
+       if (mpt3sas_scsi_direct_io_get(ioc, smid) &&
+            ((ioc_status & MPI2_IOCSTATUS_MASK)
+             != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
+               spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+               ioc->scsi_lookup[smid - 1].scmd = scmd;
+               spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+               mpt3sas_scsi_direct_io_set(ioc, smid, 0);
+               memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
+               mpi_request->DevHandle =
+                   cpu_to_le16(sas_device_priv_data->sas_target->handle);
+               mpt3sas_base_put_smid_scsi_io(ioc, smid,
+                   sas_device_priv_data->sas_target->handle);
+               return 0;
+       }
        /* turning off TLR */
        scsi_state = mpi_reply->SCSIState;
        if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
@@ -4235,10 +4466,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
                    le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
        if (!sas_device_priv_data->tlr_snoop_check) {
                sas_device_priv_data->tlr_snoop_check++;
-               if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
-                   response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
-                       sas_device_priv_data->flags &=
-                           ~MPT_DEVICE_TLR_ON;
+               if (!ioc->is_warpdrive &&
+                   !scsih_is_raid(&scmd->device->sdev_gendev) &&
+                   sas_is_tlr_enabled(scmd->device) &&
+                   response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
+                       sas_disable_tlr(scmd->device);
+                       sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
+               }
        }
 
        xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
@@ -4271,13 +4505,11 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
                            le16_to_cpu(mpi_reply->DevHandle));
                mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
                if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
                     ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
                     (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
                     (scmd->sense_buffer[2] == HARDWARE_ERROR)))
                        _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
-#endif
        }
        switch (ioc_status) {
        case MPI2_IOCSTATUS_BUSY:
@@ -4384,10 +4616,8 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
 
        }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
                _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
-#endif
 
  out:
 
@@ -4933,13 +5163,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
            sas_address);
 
-       if (!sas_device) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
-       }
+       if (!sas_device)
+               goto out_unlock;
 
        if (unlikely(sas_device->handle != handle)) {
                starget = sas_device->starget;
@@ -4967,20 +5195,25 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
                pr_err(MPT3SAS_FMT
                        "device is not present handle(0x%04x), flags!!!\n",
                        ioc->name, handle);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
+               goto out_unlock;
        }
 
        /* check if there were any issues with discovery */
        if (_scsih_check_access_status(ioc, sas_address, handle,
-           sas_device_pg0.AccessStatus)) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
-       }
+           sas_device_pg0.AccessStatus))
+               goto out_unlock;
 
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        _scsih_ublock_io_device(ioc, sas_address);
 
+       if (sas_device)
+               sas_device_put(sas_device);
+       return;
+
+out_unlock:
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       if (sas_device)
+               sas_device_put(sas_device);
 }
 
 /**
@@ -5005,7 +5238,6 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
        u32 ioc_status;
        u64 sas_address;
        u32 device_info;
-       unsigned long flags;
 
        if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
            MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
@@ -5041,13 +5273,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
            sas_device_pg0.AccessStatus))
                return -1;
 
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
-           sas_address);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-
-       if (sas_device)
+       sas_device = mpt3sas_get_sdev_by_addr(ioc,
+                                       sas_address);
+       if (sas_device) {
+               sas_device_put(sas_device);
                return -1;
+       }
 
        sas_device = kzalloc(sizeof(struct _sas_device),
            GFP_KERNEL);
@@ -5057,6 +5288,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
                return 0;
        }
 
+       kref_init(&sas_device->refcount);
        sas_device->handle = handle;
        if (_scsih_get_sas_address(ioc,
            le16_to_cpu(sas_device_pg0.ParentDevHandle),
@@ -5098,6 +5330,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
        else
                _scsih_sas_device_add(ioc, sas_device);
 
+       sas_device_put(sas_device);
        return 0;
 }
 
@@ -5144,7 +5377,9 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
                sas_target_priv_data->handle =
                     MPT3SAS_INVALID_DEVICE_HANDLE;
        }
-       mpt3sas_transport_port_remove(ioc,
+
+       if (!ioc->hide_drives)
+               mpt3sas_transport_port_remove(ioc,
                    sas_device->sas_address,
                    sas_device->sas_address_parent);
 
@@ -5180,11 +5415,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
                    "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
                    ioc->name, __func__, sas_device->enclosure_level,
                    sas_device->connector_name));
-
-       kfree(sas_device);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_topology_change_event_debug - debug for topology event
  * @ioc: per adapter object
@@ -5262,7 +5494,6 @@ _scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
 
        }
 }
-#endif
 
 /**
  * _scsih_sas_topology_change_event - handle topology changes
@@ -5287,10 +5518,8 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataSasTopologyChangeList_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_topology_change_event_debug(ioc, event_data);
-#endif
 
        if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
                return 0;
@@ -5396,7 +5625,6 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
        return 0;
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_device_status_change_event_debug - debug for device event
  * @event_data: event data payload
@@ -5464,7 +5692,6 @@ _scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
                    event_data->ASC, event_data->ASCQ);
        pr_info("\n");
 }
-#endif
 
 /**
  * _scsih_sas_device_status_change_event - handle device status change
@@ -5486,11 +5713,9 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataSasDeviceStatusChange_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_device_status_change_event_debug(ioc,
                     event_data);
-#endif
 
        /* In MPI Revision K (0xC), the internal device reset complete was
         * implemented, so avoid setting tm_busy flag for older firmware.
@@ -5506,29 +5731,30 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        sas_address = le64_to_cpu(event_data->SASAddress);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
            sas_address);
 
-       if (!sas_device || !sas_device->starget) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
-       }
+       if (!sas_device || !sas_device->starget)
+               goto out;
 
        target_priv_data = sas_device->starget->hostdata;
-       if (!target_priv_data) {
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               return;
-       }
+       if (!target_priv_data)
+               goto out;
 
        if (event_data->ReasonCode ==
            MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
                target_priv_data->tm_busy = 1;
        else
                target_priv_data->tm_busy = 0;
+
+out:
+       if (sas_device)
+               sas_device_put(sas_device);
+
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
  * event
@@ -5563,7 +5789,6 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
            (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
            le16_to_cpu(event_data->StartSlot));
 }
-#endif
 
 /**
  * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
@@ -5577,12 +5802,10 @@ static void
 _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
        struct fw_event_work *fw_event)
 {
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
                     (Mpi2EventDataSasEnclDevStatusChange_t *)
                     fw_event->event_data);
-#endif
 }
 
 /**
@@ -5762,17 +5985,15 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
        Mpi2EventDataSasDiscovery_t *event_data =
                (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
                pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
                    (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
                    "start" : "stop");
-       if (event_data->DiscoveryStatus)
-               pr_info("discovery_status(0x%08x)",
-                   le32_to_cpu(event_data->DiscoveryStatus));
-       pr_info("\n");
+               if (event_data->DiscoveryStatus)
+                       pr_info("discovery_status(0x%08x)",
+                           le32_to_cpu(event_data->DiscoveryStatus));
+               pr_info("\n");
        }
-#endif
 
        if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
            !ioc->sas_hba.num_phys) {
@@ -5804,6 +6025,8 @@ _scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
        u16 ioc_status;
        u32 log_info;
 
+       if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
+               return rc;
 
        mutex_lock(&ioc->scsih_cmds.mutex);
 
@@ -5971,7 +6194,7 @@ _scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        struct scsi_target *starget = NULL;
 
        spin_lock_irqsave(&ioc->raid_device_lock, flags);
-       raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+       raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
        if (raid_device) {
                if (raid_device->starget) {
                        starget = raid_device->starget;
@@ -6008,7 +6231,7 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
        u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
        if (sas_device) {
                sas_device->volume_handle = 0;
                sas_device->volume_wwid = 0;
@@ -6027,6 +6250,8 @@ _scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
        /* exposing raid component */
        if (starget)
                starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
+
+       sas_device_put(sas_device);
 }
 
 /**
@@ -6055,7 +6280,7 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
                    &volume_wwid);
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
        if (sas_device) {
                set_bit(handle, ioc->pd_handles);
                if (sas_device->starget && sas_device->starget->hostdata) {
@@ -6073,8 +6298,11 @@ _scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
 
        /* hiding raid component */
        _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+
        if (starget)
                starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
+
+       sas_device_put(sas_device);
 }
 
 /**
@@ -6107,7 +6335,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
        Mpi2EventIrConfigElement_t *element)
 {
        struct _sas_device *sas_device;
-       unsigned long flags;
        u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasDevicePage0_t sas_device_pg0;
@@ -6117,11 +6344,10 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
 
        set_bit(handle, ioc->pd_handles);
 
-       spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
-       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+       sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
        if (sas_device) {
                _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
+               sas_device_put(sas_device);
                return;
        }
 
@@ -6149,7 +6375,6 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
        _scsih_add_device(ioc, handle, 0, 1);
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
  * @ioc: per adapter object
@@ -6229,7 +6454,6 @@ _scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
                    element->PhysDiskNum);
        }
 }
-#endif
 
 /**
  * _scsih_sas_ir_config_change_event - handle ir configuration change events
@@ -6250,18 +6474,16 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
                (Mpi2EventDataIrConfigChangeList_t *)
                fw_event->event_data;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
-       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+       if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
+            (!ioc->hide_ir_msg))
                _scsih_sas_ir_config_change_event_debug(ioc, event_data);
 
-#endif
-
        foreign_config = (le32_to_cpu(event_data->Flags) &
            MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
 
        element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
-       if (ioc->shost_recovery) {
-
+       if (ioc->shost_recovery &&
+           ioc->hba_mpi_version_belonged != MPI2_VERSION) {
                for (i = 0; i < event_data->NumElements; i++, element++) {
                        if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
                                _scsih_ir_fastpath(ioc,
@@ -6270,6 +6492,7 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
                }
                return;
        }
+
        for (i = 0; i < event_data->NumElements; i++, element++) {
 
                switch (element->ReasonCode) {
@@ -6285,16 +6508,20 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
                                    le16_to_cpu(element->VolDevHandle));
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
-                       _scsih_sas_pd_hide(ioc, element);
+                       if (!ioc->is_warpdrive)
+                               _scsih_sas_pd_hide(ioc, element);
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
-                       _scsih_sas_pd_expose(ioc, element);
+                       if (!ioc->is_warpdrive)
+                               _scsih_sas_pd_expose(ioc, element);
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_HIDE:
-                       _scsih_sas_pd_add(ioc, element);
+                       if (!ioc->is_warpdrive)
+                               _scsih_sas_pd_add(ioc, element);
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
-                       _scsih_sas_pd_delete(ioc, element);
+                       if (!ioc->is_warpdrive)
+                               _scsih_sas_pd_delete(ioc, element);
                        break;
                }
        }
@@ -6329,10 +6556,11 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
 
        handle = le16_to_cpu(event_data->VolDevHandle);
        state = le32_to_cpu(event_data->NewValue);
-       dewtprintk(ioc, pr_info(MPT3SAS_FMT
-               "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
-               ioc->name, __func__,  handle,
-           le32_to_cpu(event_data->PreviousValue), state));
+       if (!ioc->hide_ir_msg)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+                   ioc->name, __func__,  handle,
+                   le32_to_cpu(event_data->PreviousValue), state));
        switch (state) {
        case MPI2_RAID_VOL_STATE_MISSING:
        case MPI2_RAID_VOL_STATE_FAILED:
@@ -6344,7 +6572,7 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
        case MPI2_RAID_VOL_STATE_OPTIMAL:
 
                spin_lock_irqsave(&ioc->raid_device_lock, flags);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
                spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
 
                if (raid_device)
@@ -6398,7 +6626,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        u16 handle, parent_handle;
        u32 state;
        struct _sas_device *sas_device;
-       unsigned long flags;
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasDevicePage0_t sas_device_pg0;
        u32 ioc_status;
@@ -6415,10 +6642,12 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        handle = le16_to_cpu(event_data->PhysDiskDevHandle);
        state = le32_to_cpu(event_data->NewValue);
 
-       dewtprintk(ioc, pr_info(MPT3SAS_FMT
-               "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
-               ioc->name, __func__,  handle,
+       if (!ioc->hide_ir_msg)
+               dewtprintk(ioc, pr_info(MPT3SAS_FMT
+                   "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
+                   ioc->name, __func__,  handle,
                    le32_to_cpu(event_data->PreviousValue), state));
+
        switch (state) {
        case MPI2_RAID_PD_STATE_ONLINE:
        case MPI2_RAID_PD_STATE_DEGRADED:
@@ -6426,13 +6655,14 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        case MPI2_RAID_PD_STATE_OPTIMAL:
        case MPI2_RAID_PD_STATE_HOT_SPARE:
 
-               set_bit(handle, ioc->pd_handles);
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               if (!ioc->is_warpdrive)
+                       set_bit(handle, ioc->pd_handles);
 
-               if (sas_device)
+               sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
+               if (sas_device) {
+                       sas_device_put(sas_device);
                        return;
+               }
 
                if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
                    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
@@ -6467,7 +6697,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
        }
 }
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
 /**
  * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
  * @ioc: per adapter object
@@ -6509,7 +6738,6 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
            le16_to_cpu(event_data->VolDevHandle),
            event_data->PercentComplete);
 }
-#endif
 
 /**
  * _scsih_sas_ir_operation_status_event - handle RAID operation events
@@ -6530,18 +6758,17 @@ _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
        unsigned long flags;
        u16 handle;
 
-#ifdef CONFIG_SCSI_MPT3SAS_LOGGING
-       if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+       if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
+           (!ioc->hide_ir_msg))
                _scsih_sas_ir_operation_status_event_debug(ioc,
                     event_data);
-#endif
 
        /* code added for raid transport support */
        if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
 
                spin_lock_irqsave(&ioc->raid_device_lock, flags);
                handle = le16_to_cpu(event_data->VolDevHandle);
-               raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+               raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
                if (raid_device)
                        raid_device->percent_complete =
                            event_data->PercentComplete;
@@ -6703,7 +6930,7 @@ static void
 _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
        u16 handle)
 {
-       struct MPT3SAS_TARGET *sas_target_priv_data;
+       struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
        struct scsi_target *starget;
        struct _raid_device *raid_device;
        unsigned long flags;
@@ -6722,6 +6949,13 @@ _scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
                        starget_printk(KERN_INFO, raid_device->starget,
                            "handle(0x%04x), wwid(0x%016llx)\n", handle,
                            (unsigned long long)raid_device->wwid);
+
+                       /*
+                        * WARPDRIVE: The handles of the PDs might have changed
+                        * across the host reset so re-initialize the
+                        * required data for Direct IO
+                        */
+                       mpt3sas_init_warpdrive_properties(ioc, raid_device);
                        spin_lock_irqsave(&ioc->raid_device_lock, flags);
                        if (raid_device->handle == handle) {
                                spin_unlock_irqrestore(&ioc->raid_device_lock,
@@ -6791,6 +7025,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
        }
 
        /* refresh the pd_handles */
+       if (!ioc->is_warpdrive) {
                phys_disk_num = 0xFF;
                memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
                while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
@@ -6804,6 +7039,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
                        handle = le16_to_cpu(pd_pg0.DevHandle);
                        set_bit(handle, ioc->pd_handles);
                }
+       }
  out:
        pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
                ioc->name);
@@ -6906,6 +7142,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
        struct _raid_device *raid_device, *raid_device_next;
        struct list_head tmp_list;
        unsigned long flags;
+       LIST_HEAD(head);
 
        pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
            ioc->name);
@@ -6913,14 +7150,28 @@ _scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
        /* removing unresponding end devices */
        pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
            ioc->name);
+       /*
+        * Iterate, pulling off devices marked as non-responding. We become the
+        * owner for the reference the list had on any object we prune.
+        */
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
        list_for_each_entry_safe(sas_device, sas_device_next,
            &ioc->sas_device_list, list) {
                if (!sas_device->responding)
-                       mpt3sas_device_remove_by_sas_address(ioc,
-                           sas_device->sas_address);
+                       list_move_tail(&sas_device->list, &head);
                else
                        sas_device->responding = 0;
        }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       /*
+        * Now, uninitialize and remove the unresponding devices we pruned.
+        */
+       list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
+               _scsih_remove_device(ioc, sas_device);
+               list_del_init(&sas_device->list);
+               sas_device_put(sas_device);
+       }
 
        /* removing unresponding volumes */
        if (ioc->ir_firmware) {
@@ -7074,11 +7325,11 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
                }
                phys_disk_num = pd_pg0.PhysDiskNum;
                handle = le16_to_cpu(pd_pg0.DevHandle);
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               if (sas_device)
+               sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
+               if (sas_device) {
+                       sas_device_put(sas_device);
                        continue;
+               }
                if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
                    &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
                    handle) != 0)
@@ -7199,12 +7450,12 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
                if (!(_scsih_is_end_device(
                    le32_to_cpu(sas_device_pg0.DeviceInfo))))
                        continue;
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+               sas_device = mpt3sas_get_sdev_by_addr(ioc,
                    le64_to_cpu(sas_device_pg0.SASAddress));
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-               if (sas_device)
+               if (sas_device) {
+                       sas_device_put(sas_device);
                        continue;
+               }
                parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
                if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
                        pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
@@ -7296,10 +7547,11 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
 static void
 _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
 {
+       _scsih_fw_event_del_from_list(ioc, fw_event);
+
        /* the queue is being flushed so ignore this event */
-       if (ioc->remove_host ||
-           ioc->pci_error_recovery) {
-               _scsih_fw_event_free(ioc, fw_event);
+       if (ioc->remove_host || ioc->pci_error_recovery) {
+               fw_event_work_put(fw_event);
                return;
        }
 
@@ -7310,8 +7562,16 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
                        fw_event->event_data);
                break;
        case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
-               while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
+               while (scsi_host_in_recovery(ioc->shost) ||
+                                        ioc->shost_recovery) {
+                       /*
+                        * If we're unloading, bail. Otherwise, this can become
+                        * an infinite loop.
+                        */
+                       if (ioc->remove_host)
+                               goto out;
                        ssleep(1);
+               }
                _scsih_remove_unresponding_sas_devices(ioc);
                _scsih_scan_for_devices_after_reset(ioc);
                break;
@@ -7356,7 +7616,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
                _scsih_sas_ir_operation_status_event(ioc, fw_event);
                break;
        }
-       _scsih_fw_event_free(ioc, fw_event);
+out:
+       fw_event_work_put(fw_event);
 }
 
 /**
@@ -7453,7 +7714,53 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
                    (Mpi2EventDataIrVolume_t *)
                    mpi_reply->EventData);
                break;
+       case MPI2_EVENT_LOG_ENTRY_ADDED:
+       {
+               Mpi2EventDataLogEntryAdded_t *log_entry;
+               u32 *log_code;
+
+               if (!ioc->is_warpdrive)
+                       break;
+
+               log_entry = (Mpi2EventDataLogEntryAdded_t *)
+                   mpi_reply->EventData;
+               log_code = (u32 *)log_entry->LogData;
 
+               if (le16_to_cpu(log_entry->LogEntryQualifier)
+                   != MPT2_WARPDRIVE_LOGENTRY)
+                       break;
+
+               switch (le32_to_cpu(*log_code)) {
+               case MPT2_WARPDRIVE_LC_SSDT:
+                       pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
+                           "IO Throttling has occurred in the WarpDrive "
+                           "subsystem. Check WarpDrive documentation for "
+                           "additional details.\n", ioc->name);
+                       break;
+               case MPT2_WARPDRIVE_LC_SSDLW:
+                       pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
+                           "Program/Erase Cycles for the WarpDrive subsystem "
+                           "in degraded range. Check WarpDrive documentation "
+                           "for additional details.\n", ioc->name);
+                       break;
+               case MPT2_WARPDRIVE_LC_SSDLF:
+                       pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
+                           "There are no Program/Erase Cycles for the "
+                           "WarpDrive subsystem. The storage device will be "
+                           "in read-only mode. Check WarpDrive documentation "
+                           "for additional details.\n", ioc->name);
+                       break;
+               case MPT2_WARPDRIVE_LC_BRMF:
+                       pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
+                           "The Backup Rail Monitor has failed on the "
+                           "WarpDrive subsystem. Check WarpDrive "
+                           "documentation for additional details.\n",
+                           ioc->name);
+                       break;
+               }
+
+               break;
+       }
        case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
        case MPI2_EVENT_IR_OPERATION_STATUS:
        case MPI2_EVENT_SAS_DISCOVERY:
@@ -7472,7 +7779,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
        }
 
        sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
-       fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
+       fw_event = alloc_fw_event_work(sz);
        if (!fw_event) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
@@ -7485,39 +7792,10 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
        fw_event->VP_ID = mpi_reply->VP_ID;
        fw_event->event = event;
        _scsih_fw_event_add(ioc, fw_event);
+       fw_event_work_put(fw_event);
        return 1;
 }
 
-/* shost template */
-static struct scsi_host_template scsih_driver_template = {
-       .module                         = THIS_MODULE,
-       .name                           = "Fusion MPT SAS Host",
-       .proc_name                      = MPT3SAS_DRIVER_NAME,
-       .queuecommand                   = _scsih_qcmd,
-       .target_alloc                   = _scsih_target_alloc,
-       .slave_alloc                    = _scsih_slave_alloc,
-       .slave_configure                = _scsih_slave_configure,
-       .target_destroy                 = _scsih_target_destroy,
-       .slave_destroy                  = _scsih_slave_destroy,
-       .scan_finished                  = _scsih_scan_finished,
-       .scan_start                     = _scsih_scan_start,
-       .change_queue_depth             = _scsih_change_queue_depth,
-       .eh_abort_handler               = _scsih_abort,
-       .eh_device_reset_handler        = _scsih_dev_reset,
-       .eh_target_reset_handler        = _scsih_target_reset,
-       .eh_host_reset_handler          = _scsih_host_reset,
-       .bios_param                     = _scsih_bios_param,
-       .can_queue                      = 1,
-       .this_id                        = -1,
-       .sg_tablesize                   = MPT3SAS_SG_DEPTH,
-       .max_sectors                    = 32767,
-       .cmd_per_lun                    = 7,
-       .use_clustering                 = ENABLE_CLUSTERING,
-       .shost_attrs                    = mpt3sas_host_attrs,
-       .sdev_attrs                     = mpt3sas_dev_attrs,
-       .track_queue_depth              = 1,
-};
-
 /**
  * _scsih_expander_node_remove - removing expander device from list.
  * @ioc: per adapter object
@@ -7613,7 +7891,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
        mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
        mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
 
-       pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
+       if (!ioc->hide_ir_msg)
+               pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
        init_completion(&ioc->scsih_cmds.done);
        mpt3sas_base_put_smid_default(ioc, smid);
        wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
@@ -7626,10 +7905,11 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 
        if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
                mpi_reply = ioc->scsih_cmds.reply;
-               pr_info(MPT3SAS_FMT
-                       "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
-                   ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
-                   le32_to_cpu(mpi_reply->IOCLogInfo));
+               if (!ioc->hide_ir_msg)
+                       pr_info(MPT3SAS_FMT "IR shutdown "
+                          "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
+                           ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+                           le32_to_cpu(mpi_reply->IOCLogInfo));
        }
 
  out:
@@ -7638,13 +7918,13 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
- * _scsih_remove - detach and remove add host
+ * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
  * Routine called when unloading the driver.
  * Return nothing.
  */
-static void _scsih_remove(struct pci_dev *pdev)
+void scsih_remove(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7705,18 +7985,20 @@ static void _scsih_remove(struct pci_dev *pdev)
        sas_remove_host(shost);
        scsi_remove_host(shost);
        mpt3sas_base_detach(ioc);
+       spin_lock(&gioc_lock);
        list_del(&ioc->list);
+       spin_unlock(&gioc_lock);
        scsi_host_put(shost);
 }
 
 /**
- * _scsih_shutdown - routine call during system shutdown
+ * scsih_shutdown - routine call during system shutdown
  * @pdev: PCI device struct
  *
  * Return nothing.
  */
-static void
-_scsih_shutdown(struct pci_dev *pdev)
+void
+scsih_shutdown(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -7794,6 +8076,8 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
                list_move_tail(&sas_device->list, &ioc->sas_device_list);
                spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
+               if (ioc->hide_drives)
+                       return;
                if (!mpt3sas_transport_port_add(ioc, handle,
                    sas_address_parent)) {
                        _scsih_sas_device_remove(ioc, sas_device);
@@ -7831,6 +8115,48 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
        }
 }
 
+static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
+{
+       struct _sas_device *sas_device = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+       if (!list_empty(&ioc->sas_device_init_list)) {
+               sas_device = list_first_entry(&ioc->sas_device_init_list,
+                               struct _sas_device, list);
+               sas_device_get(sas_device);
+       }
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+       return sas_device;
+}
+
+static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
+               struct _sas_device *sas_device)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ioc->sas_device_lock, flags);
+
+       /*
+        * Since we dropped the lock during the call to port_add(), we need to
+        * be careful here that somebody else didn't move or delete this item
+        * while we were busy with other things.
+        *
+        * If it was on the list, we need a put() for the reference the list
+        * had. Either way, we need a get() for the destination list.
+        */
+       if (!list_empty(&sas_device->list)) {
+               list_del_init(&sas_device->list);
+               sas_device_put(sas_device);
+       }
+
+       sas_device_get(sas_device);
+       list_add_tail(&sas_device->list, &ioc->sas_device_list);
+
+       spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
 /**
  * _scsih_probe_sas - reporting sas devices to sas transport
  * @ioc: per adapter object
@@ -7840,17 +8166,16 @@ _scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
 static void
 _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
 {
-       struct _sas_device *sas_device, *next;
-       unsigned long flags;
+       struct _sas_device *sas_device;
 
-       /* SAS Device List */
-       list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
-           list) {
+       if (ioc->hide_drives)
+               return;
 
+       while ((sas_device = get_next_sas_device(ioc))) {
                if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
                    sas_device->sas_address_parent)) {
-                       list_del(&sas_device->list);
-                       kfree(sas_device);
+                       _scsih_sas_device_remove(ioc, sas_device);
+                       sas_device_put(sas_device);
                        continue;
                } else if (!sas_device->starget) {
                        /*
@@ -7863,15 +8188,13 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
                                mpt3sas_transport_port_remove(ioc,
                                    sas_device->sas_address,
                                    sas_device->sas_address_parent);
-                               list_del(&sas_device->list);
-                               kfree(sas_device);
+                               _scsih_sas_device_remove(ioc, sas_device);
+                               sas_device_put(sas_device);
                                continue;
                        }
                }
-
-               spin_lock_irqsave(&ioc->sas_device_lock, flags);
-               list_move_tail(&sas_device->list, &ioc->sas_device_list);
-               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+               sas_device_make_active(ioc, sas_device);
+               sas_device_put(sas_device);
        }
 }
 
@@ -7908,15 +8231,15 @@ _scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
- * _scsih_scan_start - scsi lld callback for .scan_start
+ * scsih_scan_start - scsi lld callback for .scan_start
  * @shost: SCSI host pointer
  *
  * The shost has the ability to discover targets on its own instead
  * of scanning the entire bus.  In our implemention, we will kick off
  * firmware discovery.
  */
-static void
-_scsih_scan_start(struct Scsi_Host *shost)
+void
+scsih_scan_start(struct Scsi_Host *shost)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
        int rc;
@@ -7934,7 +8257,7 @@ _scsih_scan_start(struct Scsi_Host *shost)
 }
 
 /**
- * _scsih_scan_finished - scsi lld callback for .scan_finished
+ * scsih_scan_finished - scsi lld callback for .scan_finished
  * @shost: SCSI host pointer
  * @time: elapsed time of the scan in jiffies
  *
@@ -7942,8 +8265,8 @@ _scsih_scan_start(struct Scsi_Host *shost)
  * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
  * we wait for firmware discovery to complete, then return 1.
  */
-static int
-_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
+int
+scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
 {
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
 
@@ -7987,6 +8310,124 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
        return 1;
 }
 
+/* shost template for SAS 2.0 HBA devices */
+static struct scsi_host_template mpt2sas_driver_template = {
+       .module                         = THIS_MODULE,
+       .name                           = "Fusion MPT SAS Host",
+       .proc_name                      = MPT2SAS_DRIVER_NAME,
+       .queuecommand                   = scsih_qcmd,
+       .target_alloc                   = scsih_target_alloc,
+       .slave_alloc                    = scsih_slave_alloc,
+       .slave_configure                = scsih_slave_configure,
+       .target_destroy                 = scsih_target_destroy,
+       .slave_destroy                  = scsih_slave_destroy,
+       .scan_finished                  = scsih_scan_finished,
+       .scan_start                     = scsih_scan_start,
+       .change_queue_depth             = scsih_change_queue_depth,
+       .eh_abort_handler               = scsih_abort,
+       .eh_device_reset_handler        = scsih_dev_reset,
+       .eh_target_reset_handler        = scsih_target_reset,
+       .eh_host_reset_handler          = scsih_host_reset,
+       .bios_param                     = scsih_bios_param,
+       .can_queue                      = 1,
+       .this_id                        = -1,
+       .sg_tablesize                   = MPT2SAS_SG_DEPTH,
+       .max_sectors                    = 32767,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+       .shost_attrs                    = mpt3sas_host_attrs,
+       .sdev_attrs                     = mpt3sas_dev_attrs,
+       .track_queue_depth              = 1,
+};
+
+/* raid transport support for SAS 2.0 HBA devices */
+static struct raid_function_template mpt2sas_raid_functions = {
+       .cookie         = &mpt2sas_driver_template,
+       .is_raid        = scsih_is_raid,
+       .get_resync     = scsih_get_resync,
+       .get_state      = scsih_get_state,
+};
+
+/* shost template for SAS 3.0 HBA devices */
+static struct scsi_host_template mpt3sas_driver_template = {
+       .module                         = THIS_MODULE,
+       .name                           = "Fusion MPT SAS Host",
+       .proc_name                      = MPT3SAS_DRIVER_NAME,
+       .queuecommand                   = scsih_qcmd,
+       .target_alloc                   = scsih_target_alloc,
+       .slave_alloc                    = scsih_slave_alloc,
+       .slave_configure                = scsih_slave_configure,
+       .target_destroy                 = scsih_target_destroy,
+       .slave_destroy                  = scsih_slave_destroy,
+       .scan_finished                  = scsih_scan_finished,
+       .scan_start                     = scsih_scan_start,
+       .change_queue_depth             = scsih_change_queue_depth,
+       .eh_abort_handler               = scsih_abort,
+       .eh_device_reset_handler        = scsih_dev_reset,
+       .eh_target_reset_handler        = scsih_target_reset,
+       .eh_host_reset_handler          = scsih_host_reset,
+       .bios_param                     = scsih_bios_param,
+       .can_queue                      = 1,
+       .this_id                        = -1,
+       .sg_tablesize                   = MPT3SAS_SG_DEPTH,
+       .max_sectors                    = 32767,
+       .cmd_per_lun                    = 7,
+       .use_clustering                 = ENABLE_CLUSTERING,
+       .shost_attrs                    = mpt3sas_host_attrs,
+       .sdev_attrs                     = mpt3sas_dev_attrs,
+       .track_queue_depth              = 1,
+};
+
+/* raid transport support for SAS 3.0 HBA devices */
+static struct raid_function_template mpt3sas_raid_functions = {
+       .cookie         = &mpt3sas_driver_template,
+       .is_raid        = scsih_is_raid,
+       .get_resync     = scsih_get_resync,
+       .get_state      = scsih_get_state,
+};
+
+/**
+ * _scsih_determine_hba_mpi_version - determine in which MPI version class
+ *                                     this device belongs to.
+ * @pdev: PCI device struct
+ *
+ * return MPI2_VERSION for SAS 2.0 HBA devices,
+ *     MPI25_VERSION for SAS 3.0 HBA devices.
+ */
+u16
+_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
+{
+
+       switch (pdev->device) {
+       case MPI2_MFGPAGE_DEVID_SSS6200:
+       case MPI2_MFGPAGE_DEVID_SAS2004:
+       case MPI2_MFGPAGE_DEVID_SAS2008:
+       case MPI2_MFGPAGE_DEVID_SAS2108_1:
+       case MPI2_MFGPAGE_DEVID_SAS2108_2:
+       case MPI2_MFGPAGE_DEVID_SAS2108_3:
+       case MPI2_MFGPAGE_DEVID_SAS2116_1:
+       case MPI2_MFGPAGE_DEVID_SAS2116_2:
+       case MPI2_MFGPAGE_DEVID_SAS2208_1:
+       case MPI2_MFGPAGE_DEVID_SAS2208_2:
+       case MPI2_MFGPAGE_DEVID_SAS2208_3:
+       case MPI2_MFGPAGE_DEVID_SAS2208_4:
+       case MPI2_MFGPAGE_DEVID_SAS2208_5:
+       case MPI2_MFGPAGE_DEVID_SAS2208_6:
+       case MPI2_MFGPAGE_DEVID_SAS2308_1:
+       case MPI2_MFGPAGE_DEVID_SAS2308_2:
+       case MPI2_MFGPAGE_DEVID_SAS2308_3:
+               return MPI2_VERSION;
+       case MPI25_MFGPAGE_DEVID_SAS3004:
+       case MPI25_MFGPAGE_DEVID_SAS3008:
+       case MPI25_MFGPAGE_DEVID_SAS3108_1:
+       case MPI25_MFGPAGE_DEVID_SAS3108_2:
+       case MPI25_MFGPAGE_DEVID_SAS3108_5:
+       case MPI25_MFGPAGE_DEVID_SAS3108_6:
+               return MPI25_VERSION;
+       }
+       return 0;
+}
+
 /**
  * _scsih_probe - attach and add scsi host
  * @pdev: PCI device struct
@@ -7994,26 +8435,72 @@ _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
  *
  * Returns 0 success, anything else error.
  */
-static int
+int
 _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct MPT3SAS_ADAPTER *ioc;
-       struct Scsi_Host *shost;
+       struct Scsi_Host *shost = NULL;
        int rv;
+       u16 hba_mpi_version;
 
-       shost = scsi_host_alloc(&scsih_driver_template,
-           sizeof(struct MPT3SAS_ADAPTER));
-       if (!shost)
+       /* Determine in which MPI version class this pci device belongs */
+       hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
+       if (hba_mpi_version == 0)
                return -ENODEV;
 
-       /* init local params */
-       ioc = shost_priv(shost);
-       memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+       /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one,
+        * for other generation HBA's return with -ENODEV
+        */
+       if ((hbas_to_enumerate == 1) && (hba_mpi_version !=  MPI2_VERSION))
+               return -ENODEV;
+
+       /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two,
+        * for other generation HBA's return with -ENODEV
+        */
+       if ((hbas_to_enumerate == 2) && (hba_mpi_version !=  MPI25_VERSION))
+               return -ENODEV;
+
+       switch (hba_mpi_version) {
+       case MPI2_VERSION:
+               /* Use mpt2sas driver host template for SAS 2.0 HBA's */
+               shost = scsi_host_alloc(&mpt2sas_driver_template,
+                 sizeof(struct MPT3SAS_ADAPTER));
+               if (!shost)
+                       return -ENODEV;
+               ioc = shost_priv(shost);
+               memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+               ioc->hba_mpi_version_belonged = hba_mpi_version;
+               ioc->id = mpt2_ids++;
+               sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
+               if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
+                       ioc->is_warpdrive = 1;
+                       ioc->hide_ir_msg = 1;
+               } else
+                       ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
+               break;
+       case MPI25_VERSION:
+               /* Use mpt3sas driver host template for SAS 3.0 HBA's */
+               shost = scsi_host_alloc(&mpt3sas_driver_template,
+                 sizeof(struct MPT3SAS_ADAPTER));
+               if (!shost)
+                       return -ENODEV;
+               ioc = shost_priv(shost);
+               memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
+               ioc->hba_mpi_version_belonged = hba_mpi_version;
+               ioc->id = mpt3_ids++;
+               sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
+               if (pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION)
+                       ioc->msix96_vector = 1;
+               break;
+       default:
+               return -ENODEV;
+       }
+
        INIT_LIST_HEAD(&ioc->list);
+       spin_lock(&gioc_lock);
        list_add_tail(&ioc->list, &mpt3sas_ioc_list);
+       spin_unlock(&gioc_lock);
        ioc->shost = shost;
-       ioc->id = mpt_ids++;
-       sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id);
        ioc->pdev = pdev;
        ioc->scsi_io_cb_idx = scsi_io_cb_idx;
        ioc->tm_cb_idx = tm_cb_idx;
@@ -8030,6 +8517,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
        /* misc semaphores and spin locks */
        mutex_init(&ioc->reset_in_progress_mutex);
+       /* initializing pci_access_mutex lock */
+       mutex_init(&ioc->pci_access_mutex);
        spin_lock_init(&ioc->ioc_reset_in_progress_lock);
        spin_lock_init(&ioc->scsi_lookup_lock);
        spin_lock_init(&ioc->sas_device_lock);
@@ -8048,6 +8537,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
        INIT_LIST_HEAD(&ioc->reply_queue_list);
 
+       sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id);
+
        /* init shost parameters */
        shost->max_cmd_len = 32;
        shost->max_lun = max_lun;
@@ -8086,7 +8577,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* event thread */
        snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
-           "fw_event%d", ioc->id);
+           "fw_event_%s%d", ioc->driver_name, ioc->id);
        ioc->firmware_event_thread = alloc_ordered_workqueue(
            ioc->firmware_event_name, WQ_MEM_RECLAIM);
        if (!ioc->firmware_event_thread) {
@@ -8103,6 +8594,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                rv = -ENODEV;
                goto out_attach_fail;
        }
+
+       if (ioc->is_warpdrive) {
+               if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_EXPOSE_ALL_DISKS)
+                       ioc->hide_drives = 0;
+               else if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_HIDE_ALL_DISKS)
+                       ioc->hide_drives = 1;
+               else {
+                       if (mpt3sas_get_num_volumes(ioc))
+                               ioc->hide_drives = 1;
+                       else
+                               ioc->hide_drives = 0;
+               }
+       } else
+               ioc->hide_drives = 0;
+
        rv = scsi_add_host(shost, &pdev->dev);
        if (rv) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
@@ -8117,21 +8623,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  out_attach_fail:
        destroy_workqueue(ioc->firmware_event_thread);
  out_thread_fail:
+       spin_lock(&gioc_lock);
        list_del(&ioc->list);
+       spin_unlock(&gioc_lock);
        scsi_host_put(shost);
        return rv;
 }
 
 #ifdef CONFIG_PM
 /**
- * _scsih_suspend - power management suspend main entry point
+ * scsih_suspend - power management suspend main entry point
  * @pdev: PCI device struct
  * @state: PM state change to (usually PCI_D3)
  *
  * Returns 0 success, anything else error.
  */
-static int
-_scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+int
+scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8152,13 +8660,13 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 }
 
 /**
- * _scsih_resume - power management resume main entry point
+ * scsih_resume - power management resume main entry point
  * @pdev: PCI device struct
  *
  * Returns 0 success, anything else error.
  */
-static int
-_scsih_resume(struct pci_dev *pdev)
+int
+scsih_resume(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8185,7 +8693,7 @@ _scsih_resume(struct pci_dev *pdev)
 #endif /* CONFIG_PM */
 
 /**
- * _scsih_pci_error_detected - Called when a PCI error is detected.
+ * scsih_pci_error_detected - Called when a PCI error is detected.
  * @pdev: PCI device struct
  * @state: PCI channel state
  *
@@ -8194,8 +8702,8 @@ _scsih_resume(struct pci_dev *pdev)
  * Return value:
  *      PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
  */
-static pci_ers_result_t
-_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+pci_ers_result_t
+scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8224,15 +8732,15 @@ _scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 }
 
 /**
- * _scsih_pci_slot_reset - Called when PCI slot has been reset.
+ * scsih_pci_slot_reset - Called when PCI slot has been reset.
  * @pdev: PCI device struct
  *
  * Description: This routine is called by the pci error recovery
  * code after the PCI slot has been reset, just before we
  * should resume normal operations.
  */
-static pci_ers_result_t
-_scsih_pci_slot_reset(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_slot_reset(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8261,15 +8769,15 @@ _scsih_pci_slot_reset(struct pci_dev *pdev)
 }
 
 /**
- * _scsih_pci_resume() - resume normal ops after PCI reset
+ * scsih_pci_resume() - resume normal ops after PCI reset
  * @pdev: pointer to PCI device
  *
  * Called when the error recovery driver tells us that its
  * OK to resume normal operation. Use completion to allow
  * halted scsi ops to resume.
  */
-static void
-_scsih_pci_resume(struct pci_dev *pdev)
+void
+scsih_pci_resume(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8282,11 +8790,11 @@ _scsih_pci_resume(struct pci_dev *pdev)
 }
 
 /**
- * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
+ * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
  * @pdev: pointer to PCI device
  */
-static pci_ers_result_t
-_scsih_pci_mmio_enabled(struct pci_dev *pdev)
+pci_ers_result_t
+scsih_pci_mmio_enabled(struct pci_dev *pdev)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
@@ -8300,61 +8808,99 @@ _scsih_pci_mmio_enabled(struct pci_dev *pdev)
        return PCI_ERS_RESULT_NEED_RESET;
 }
 
-/* raid transport support */
-static struct raid_function_template mpt3sas_raid_functions = {
-       .cookie         = &scsih_driver_template,
-       .is_raid        = _scsih_is_raid,
-       .get_resync     = _scsih_get_resync,
-       .get_state      = _scsih_get_state,
+/*
+ * The pci device ids are defined in mpi/mpi2_cnfg.h.
+ */
+static const struct pci_device_id mpt3sas_pci_table[] = {
+       /* Spitfire ~ 2004 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Falcon ~ 2008 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Liberator ~ 2108 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Meteor ~ 2116 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Thunderbolt ~ 2208 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Mustang ~ 2308 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* SSS6200 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Fury ~ 3004 and 3008 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
+               PCI_ANY_ID, PCI_ANY_ID },
+       /* Invader ~ 3108 */
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
+               PCI_ANY_ID, PCI_ANY_ID },
+       { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
+               PCI_ANY_ID, PCI_ANY_ID },
+       {0}     /* Terminating entry */
 };
+MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
 
-static struct pci_error_handlers _scsih_err_handler = {
-       .error_detected = _scsih_pci_error_detected,
-       .mmio_enabled = _scsih_pci_mmio_enabled,
-       .slot_reset =   _scsih_pci_slot_reset,
-       .resume =       _scsih_pci_resume,
+static struct pci_error_handlers _mpt3sas_err_handler = {
+       .error_detected = scsih_pci_error_detected,
+       .mmio_enabled   = scsih_pci_mmio_enabled,
+       .slot_reset     = scsih_pci_slot_reset,
+       .resume         = scsih_pci_resume,
 };
 
-static struct pci_driver scsih_driver = {
+static struct pci_driver mpt3sas_driver = {
        .name           = MPT3SAS_DRIVER_NAME,
-       .id_table       = scsih_pci_table,
+       .id_table       = mpt3sas_pci_table,
        .probe          = _scsih_probe,
-       .remove         = _scsih_remove,
-       .shutdown       = _scsih_shutdown,
-       .err_handler    = &_scsih_err_handler,
+       .remove         = scsih_remove,
+       .shutdown       = scsih_shutdown,
+       .err_handler    = &_mpt3sas_err_handler,
 #ifdef CONFIG_PM
-       .suspend        = _scsih_suspend,
-       .resume         = _scsih_resume,
+       .suspend        = scsih_suspend,
+       .resume         = scsih_resume,
 #endif
 };
 
-
 /**
- * _scsih_init - main entry point for this driver.
+ * scsih_init - main entry point for this driver.
  *
  * Returns 0 success, anything else error.
  */
-static int __init
-_scsih_init(void)
+int
+scsih_init(void)
 {
-       int error;
-
-       mpt_ids = 0;
-
-       pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
-           MPT3SAS_DRIVER_VERSION);
-
-       mpt3sas_transport_template =
-           sas_attach_transport(&mpt3sas_transport_functions);
-       if (!mpt3sas_transport_template)
-               return -ENODEV;
-
-/* raid transport support */
-       mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions);
-       if (!mpt3sas_raid_template) {
-               sas_release_transport(mpt3sas_transport_template);
-               return -ENODEV;
-       }
+       mpt2_ids = 0;
+       mpt3_ids = 0;
 
        mpt3sas_base_initialize_callback_handler();
 
@@ -8392,33 +8938,17 @@ _scsih_init(void)
        tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
            _scsih_sas_control_complete);
 
-       mpt3sas_ctl_init();
-
-       error = pci_register_driver(&scsih_driver);
-       if (error) {
-               /* raid transport support */
-               raid_class_release(mpt3sas_raid_template);
-               sas_release_transport(mpt3sas_transport_template);
-       }
-
-       return error;
+       return 0;
 }
 
 /**
- * _scsih_exit - exit point for this driver (when it is a module).
+ * scsih_exit - exit point for this driver (when it is a module).
  *
  * Returns 0 success, anything else error.
  */
-static void __exit
-_scsih_exit(void)
+void
+scsih_exit(void)
 {
-       pr_info("mpt3sas version %s unloading\n",
-           MPT3SAS_DRIVER_VERSION);
-
-       mpt3sas_ctl_exit();
-
-       pci_unregister_driver(&scsih_driver);
-
 
        mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
        mpt3sas_base_release_callback_handler(tm_cb_idx);
@@ -8434,9 +8964,86 @@ _scsih_exit(void)
        mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
 
 /* raid transport support */
-       raid_class_release(mpt3sas_raid_template);
+       if (hbas_to_enumerate != 1)
+               raid_class_release(mpt3sas_raid_template);
+       if (hbas_to_enumerate != 2)
+               raid_class_release(mpt2sas_raid_template);
        sas_release_transport(mpt3sas_transport_template);
 }
 
-module_init(_scsih_init);
-module_exit(_scsih_exit);
+/**
+ * _mpt3sas_init - main entry point for this driver.
+ *
+ * Returns 0 success, anything else error.
+ */
+static int __init
+_mpt3sas_init(void)
+{
+       int error;
+
+       pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
+                                       MPT3SAS_DRIVER_VERSION);
+
+       mpt3sas_transport_template =
+           sas_attach_transport(&mpt3sas_transport_functions);
+       if (!mpt3sas_transport_template)
+               return -ENODEV;
+
+       /* No need attach mpt3sas raid functions template
+        * if hbas_to_enumarate value is one.
+        */
+       if (hbas_to_enumerate != 1) {
+               mpt3sas_raid_template =
+                               raid_class_attach(&mpt3sas_raid_functions);
+               if (!mpt3sas_raid_template) {
+                       sas_release_transport(mpt3sas_transport_template);
+                       return -ENODEV;
+               }
+       }
+
+       /* No need to attach mpt2sas raid functions template
+        * if hbas_to_enumarate value is two
+        */
+       if (hbas_to_enumerate != 2) {
+               mpt2sas_raid_template =
+                               raid_class_attach(&mpt2sas_raid_functions);
+               if (!mpt2sas_raid_template) {
+                       sas_release_transport(mpt3sas_transport_template);
+                       return -ENODEV;
+               }
+       }
+
+       error = scsih_init();
+       if (error) {
+               scsih_exit();
+               return error;
+       }
+
+       mpt3sas_ctl_init(hbas_to_enumerate);
+
+       error = pci_register_driver(&mpt3sas_driver);
+       if (error)
+               scsih_exit();
+
+       return error;
+}
+
+/**
+ * _mpt3sas_exit - exit point for this driver (when it is a module).
+ *
+ */
+static void __exit
+_mpt3sas_exit(void)
+{
+       pr_info("mpt3sas version %s unloading\n",
+                               MPT3SAS_DRIVER_VERSION);
+
+       pci_unregister_driver(&mpt3sas_driver);
+
+       mpt3sas_ctl_exit(hbas_to_enumerate);
+
+       scsih_exit();
+}
+
+module_init(_mpt3sas_init);
+module_exit(_mpt3sas_exit);
index 70fd019e7ee585c14deea0e4ec1ffcff66709f8e..ca36d7ea096495f6f6f659af4a92076dbf0bf485 100644 (file)
@@ -734,7 +734,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
        rphy->identify = mpt3sas_port->remote_identify;
 
        if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
-               sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+               sas_device = mpt3sas_get_sdev_by_addr(ioc,
                                    mpt3sas_port->remote_identify.sas_address);
                if (!sas_device) {
                        dfailprintk(ioc, printk(MPT3SAS_FMT
@@ -750,8 +750,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
                    ioc->name, __FILE__, __LINE__, __func__);
        }
 
-       if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
+       if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
                sas_device->pend_sas_rphy_add = 0;
+               sas_device_put(sas_device);
+       }
 
        if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
                dev_printk(KERN_INFO, &rphy->dev,
@@ -1324,15 +1326,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
        int rc;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
            rphy->identify.sas_address);
        if (sas_device) {
                *identifier = sas_device->enclosure_logical_id;
                rc = 0;
+               sas_device_put(sas_device);
        } else {
                *identifier = 0;
                rc = -ENXIO;
        }
+
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        return rc;
 }
@@ -1352,12 +1356,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
        int rc;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
-       sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
+       sas_device = __mpt3sas_get_sdev_by_addr(ioc,
            rphy->identify.sas_address);
-       if (sas_device)
+       if (sas_device) {
                rc = sas_device->slot;
-       else
+               sas_device_put(sas_device);
+       } else {
                rc = -ENXIO;
+       }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
        return rc;
 }
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
new file mode 100644 (file)
index 0000000..540bd50
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Scsi Host Layer for MPT (Message Passing Technology) based controllers
+ *
+ * Copyright (C) 2012-2014  LSI Corporation
+ * Copyright (C) 2013-2015 Avago Technologies
+ *  (mailto: MPT-FusionLinux.pdl@avagotech.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#include "mpt3sas_base.h"
+
+/**
+ * _warpdrive_disable_ddio - Disable direct I/O for all the volumes
+ * @ioc: per adapter object
+ */
+static void
+_warpdrive_disable_ddio(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2RaidVolPage1_t vol_pg1;
+       Mpi2ConfigReply_t mpi_reply;
+       struct _raid_device *raid_device;
+       u16 handle;
+       u16 ioc_status;
+       unsigned long flags;
+
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               handle = le16_to_cpu(vol_pg1.DevHandle);
+               spin_lock_irqsave(&ioc->raid_device_lock, flags);
+               raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
+               if (raid_device)
+                       raid_device->direct_io_enabled = 0;
+               spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+       }
+       return;
+}
+
+
+/**
+ * mpt3sas_get_num_volumes - Get number of volumes in the ioc
+ * @ioc: per adapter object
+ */
+u8
+mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc)
+{
+       Mpi2RaidVolPage1_t vol_pg1;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 handle;
+       u8 vol_cnt = 0;
+       u16 ioc_status;
+
+       handle = 0xFFFF;
+       while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+           &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+                       break;
+               vol_cnt++;
+               handle = le16_to_cpu(vol_pg1.DevHandle);
+       }
+       return vol_cnt;
+}
+
+
+/**
+ * mpt3sas_init_warpdrive_properties - Set properties for warpdrive direct I/O.
+ * @ioc: per adapter object
+ * @raid_device: the raid_device object
+ */
+void
+mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
+       struct _raid_device *raid_device)
+{
+       Mpi2RaidVolPage0_t *vol_pg0;
+       Mpi2RaidPhysDiskPage0_t pd_pg0;
+       Mpi2ConfigReply_t mpi_reply;
+       u16 sz;
+       u8 num_pds, count;
+       unsigned long stripe_sz, block_sz;
+       u8 stripe_exp, block_exp;
+       u64 dev_max_lba;
+
+       if (!ioc->is_warpdrive)
+               return;
+
+       if (ioc->mfg_pg10_hide_flag ==  MFG_PAGE10_EXPOSE_ALL_DISKS) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "globally as drives are exposed\n", ioc->name);
+               return;
+       }
+       if (mpt3sas_get_num_volumes(ioc) > 1) {
+               _warpdrive_disable_ddio(ioc);
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "globally as number of drives > 1\n", ioc->name);
+               return;
+       }
+       if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
+           &num_pds)) || !num_pds) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "Failure in computing number of drives\n", ioc->name);
+               return;
+       }
+
+       sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
+           sizeof(Mpi2RaidVol0PhysDisk_t));
+       vol_pg0 = kzalloc(sz, GFP_KERNEL);
+       if (!vol_pg0) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "Memory allocation failure for RVPG0\n", ioc->name);
+               return;
+       }
+
+       if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
+            MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "Failure in retrieving RVPG0\n", ioc->name);
+               kfree(vol_pg0);
+               return;
+       }
+
+       /*
+        * WARPDRIVE:If number of physical disks in a volume exceeds the max pds
+        * assumed for WARPDRIVE, disable direct I/O
+        */
+       if (num_pds > MPT_MAX_WARPDRIVE_PDS) {
+               pr_warn(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "for the drive with handle(0x%04x): num_mem=%d, "
+                   "max_mem_allowed=%d\n", ioc->name, raid_device->handle,
+                   num_pds, MPT_MAX_WARPDRIVE_PDS);
+               kfree(vol_pg0);
+               return;
+       }
+       for (count = 0; count < num_pds; count++) {
+               if (mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+                   &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
+                   vol_pg0->PhysDisk[count].PhysDiskNum) ||
+                   pd_pg0.DevHandle == MPT3SAS_INVALID_DEVICE_HANDLE) {
+                       pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is "
+                           "disabled for the drive with handle(0x%04x) member"
+                           "handle retrieval failed for member number=%d\n",
+                           ioc->name, raid_device->handle,
+                           vol_pg0->PhysDisk[count].PhysDiskNum);
+                       goto out_error;
+               }
+               /* Disable direct I/O if member drive lba exceeds 4 bytes */
+               dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA);
+               if (dev_max_lba >> 32) {
+                       pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is "
+                           "disabled for the drive with handle(0x%04x) member"
+                           " handle (0x%04x) unsupported max lba 0x%016llx\n",
+                           ioc->name, raid_device->handle,
+                           le16_to_cpu(pd_pg0.DevHandle),
+                           (unsigned long long)dev_max_lba);
+                       goto out_error;
+               }
+
+               raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle);
+       }
+
+       /*
+        * Assumption for WD: Direct I/O is not supported if the volume is
+        * not RAID0
+        */
+       if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "for the drive with handle(0x%04x): type=%d, "
+                   "s_sz=%uK, blk_size=%u\n", ioc->name,
+                   raid_device->handle, raid_device->volume_type,
+                   (le32_to_cpu(vol_pg0->StripeSize) *
+                   le16_to_cpu(vol_pg0->BlockSize)) / 1024,
+                   le16_to_cpu(vol_pg0->BlockSize));
+               goto out_error;
+       }
+
+       stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
+       stripe_exp = find_first_bit(&stripe_sz, 32);
+       if (stripe_exp == 32) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+               "for the drive with handle(0x%04x) invalid stripe sz %uK\n",
+                   ioc->name, raid_device->handle,
+                   (le32_to_cpu(vol_pg0->StripeSize) *
+                   le16_to_cpu(vol_pg0->BlockSize)) / 1024);
+               goto out_error;
+       }
+       raid_device->stripe_exponent = stripe_exp;
+       block_sz = le16_to_cpu(vol_pg0->BlockSize);
+       block_exp = find_first_bit(&block_sz, 16);
+       if (block_exp == 16) {
+               pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled "
+                   "for the drive with handle(0x%04x) invalid block sz %u\n",
+                   ioc->name, raid_device->handle,
+                   le16_to_cpu(vol_pg0->BlockSize));
+               goto out_error;
+       }
+       raid_device->block_exponent = block_exp;
+       raid_device->direct_io_enabled = 1;
+
+       pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is Enabled for the drive"
+           " with handle(0x%04x)\n", ioc->name, raid_device->handle);
+       /*
+        * WARPDRIVE: Though the following fields are not used for direct IO,
+        * stored for future purpose:
+        */
+       raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA);
+       raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize);
+       raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize);
+
+
+       kfree(vol_pg0);
+       return;
+
+out_error:
+       raid_device->direct_io_enabled = 0;
+       for (count = 0; count < num_pds; count++)
+               raid_device->pd_handle[count] = 0;
+       kfree(vol_pg0);
+       return;
+}
+
+/**
+ * mpt3sas_scsi_direct_io_get - returns direct io flag
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns the smid stored scmd pointer.
+ */
+inline u8
+mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+       return ioc->scsi_lookup[smid - 1].direct_io;
+}
+
+/**
+ * mpt3sas_scsi_direct_io_set - sets direct io flag
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @direct_io: Zero or non-zero value to set in the direct_io flag
+ *
+ * Returns Nothing.
+ */
+inline void
+mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io)
+{
+       ioc->scsi_lookup[smid - 1].direct_io = direct_io;
+}
+
+/**
+ * mpt3sas_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ * @raid_device: pointer to raid device data structure
+ * @mpi_request: pointer to the SCSI_IO reqest message frame
+ * @smid: system request message index
+ *
+ * Returns nothing
+ */
+void
+mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+       struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
+       u16 smid)
+{
+       sector_t v_lba, p_lba, stripe_off, column, io_size;
+       u32 stripe_sz, stripe_exp;
+       u8 num_pds, cmd = scmd->cmnd[0];
+
+       if (cmd != READ_10 && cmd != WRITE_10 &&
+           cmd != READ_16 && cmd != WRITE_16)
+               return;
+
+       if (cmd == READ_10 || cmd == WRITE_10)
+               v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]);
+       else
+               v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]);
+
+       io_size = scsi_bufflen(scmd) >> raid_device->block_exponent;
+
+       if (v_lba + io_size - 1 > raid_device->max_lba)
+               return;
+
+       stripe_sz = raid_device->stripe_sz;
+       stripe_exp = raid_device->stripe_exponent;
+       stripe_off = v_lba & (stripe_sz - 1);
+
+       /* Return unless IO falls within a stripe */
+       if (stripe_off + io_size > stripe_sz)
+               return;
+
+       num_pds = raid_device->num_pds;
+       p_lba = v_lba >> stripe_exp;
+       column = sector_div(p_lba, num_pds);
+       p_lba = (p_lba << stripe_exp) + stripe_off;
+       mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]);
+
+       if (cmd == READ_10 || cmd == WRITE_10)
+               put_unaligned_be32(lower_32_bits(p_lba),
+                                  &mpi_request->CDB.CDB32[2]);
+       else
+               put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]);
+
+       mpt3sas_scsi_direct_io_set(ioc, smid, 1);
+}
index e2d555c1bffc16f94a87ed6b009d868cc3784a3e..90fdf0e859e31fd9e72352d2ed19a889061e6ed4 100644 (file)
@@ -65,7 +65,6 @@ static struct scsi_host_template mvs_sht = {
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
        .shost_attrs            = mvst_host_attrs,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -641,9 +640,9 @@ static void mvs_pci_remove(struct pci_dev *pdev)
        tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
 #endif
 
+       scsi_remove_host(mvi->shost);
        sas_unregister_ha(sha);
        sas_remove_host(mvi->shost);
-       scsi_remove_host(mvi->shost);
 
        MVS_CHIP_DISP->interrupt_disable(mvi);
        free_irq(mvi->pdev->irq, sha);
index 3e6b866759fef68dd80eac70ea4e35e56f955f92..02360de6b7e0dd8bd59bf7fe40e3e173d1fe7d0f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/ktime.h>
 #include <linux/blkdev.h>
 #include <linux/io.h>
 #include <scsi/scsi.h>
@@ -858,8 +859,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba,
        struct mvumi_hs_page2 *hs_page2;
        struct mvumi_hs_page4 *hs_page4;
        struct mvumi_hs_page3 *hs_page3;
-       struct timeval time;
-       unsigned int local_time;
+       u64 time;
+       u64 local_time;
 
        switch (hs_header->page_code) {
        case HS_PAGE_HOST_INFO:
@@ -877,9 +878,8 @@ static void mvumi_hs_build_page(struct mvumi_hba *mhba,
                hs_page2->slot_number = 0;
                hs_page2->intr_level = 0;
                hs_page2->intr_vector = 0;
-               do_gettimeofday(&time);
-               local_time = (unsigned int) (time.tv_sec -
-                                               (sys_tz.tz_minuteswest * 60));
+               time = ktime_get_real_seconds();
+               local_time = (time - (sys_tz.tz_minuteswest * 60));
                hs_page2->seconds_since1970 = local_time;
                hs_header->checksum = mvumi_calculate_checksum(hs_header,
                                                hs_header->frame_length);
index f14ec6e042b9ae240b9c5984688325b746496347..199527dbaaa14fa84c48deb122c9b71d1c1b171c 100644 (file)
@@ -51,6 +51,8 @@ enum chip_flavors {
        chip_8076,
        chip_8077,
        chip_8006,
+       chip_8070,
+       chip_8072
 };
 
 enum phy_speed {
index 5c0356fb6310ecfeb5c39cafe9bc75c7cb354002..062ab34b86f8bcab08d24b8cfe1e4dffa938939d 100644 (file)
@@ -58,6 +58,8 @@ static const struct pm8001_chip_info pm8001_chips[] = {
        [chip_8076] = {0,  16, &pm8001_80xx_dispatch,},
        [chip_8077] = {0,  16, &pm8001_80xx_dispatch,},
        [chip_8006] = {0,  16, &pm8001_80xx_dispatch,},
+       [chip_8070] = {0,  8, &pm8001_80xx_dispatch,},
+       [chip_8072] = {0,  16, &pm8001_80xx_dispatch,},
 };
 static int pm8001_id;
 
@@ -88,7 +90,6 @@ static struct scsi_host_template pm8001_sht = {
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
        .shost_attrs            = pm8001_host_attrs,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -480,7 +481,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 
 #ifdef PM8001_USE_TASKLET
        /* Tasklet for non msi-x interrupt handler */
-       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+       if ((!pdev->msix_cap || !pci_msi_enabled())
+           || (pm8001_ha->chip_id == chip_8001))
                tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
                        (unsigned long)&(pm8001_ha->irq_vector[0]));
        else
@@ -634,6 +636,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
                        payload.minor_function = 0;
                        payload.length = 128;
                }
+       } else if ((pm8001_ha->chip_id == chip_8070 ||
+                       pm8001_ha->chip_id == chip_8072) &&
+                       pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
+               payload.minor_function = 4;
+               payload.length = 4096;
        } else {
                payload.minor_function = 1;
                payload.length = 4096;
@@ -660,6 +667,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
                        else if (deviceid == 0x0042)
                                pm8001_ha->sas_addr[j] =
                                        payload.func_specific[0x010 + i];
+               } else if ((pm8001_ha->chip_id == chip_8070 ||
+                               pm8001_ha->chip_id == chip_8072) &&
+                               pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
+                       pm8001_ha->sas_addr[j] =
+                                       payload.func_specific[0x010 + i];
                } else
                        pm8001_ha->sas_addr[j] =
                                        payload.func_specific[0x804 + i];
@@ -720,6 +732,153 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
        return 0;
 }
 
+struct pm8001_mpi3_phy_pg_trx_config {
+       u32 LaneLosCfg;
+       u32 LanePgaCfg1;
+       u32 LanePisoCfg1;
+       u32 LanePisoCfg2;
+       u32 LanePisoCfg3;
+       u32 LanePisoCfg4;
+       u32 LanePisoCfg5;
+       u32 LanePisoCfg6;
+       u32 LaneBctCtrl;
+};
+
+/**
+ * pm8001_get_internal_phy_settings : Retrieves the internal PHY settings
+ * @pm8001_ha : our adapter
+ * @phycfg : PHY config page to populate
+ */
+static
+void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_mpi3_phy_pg_trx_config *phycfg)
+{
+       phycfg->LaneLosCfg   = 0x00000132;
+       phycfg->LanePgaCfg1  = 0x00203949;
+       phycfg->LanePisoCfg1 = 0x000000FF;
+       phycfg->LanePisoCfg2 = 0xFF000001;
+       phycfg->LanePisoCfg3 = 0xE7011300;
+       phycfg->LanePisoCfg4 = 0x631C40C0;
+       phycfg->LanePisoCfg5 = 0xF8102036;
+       phycfg->LanePisoCfg6 = 0xF74A1000;
+       phycfg->LaneBctCtrl  = 0x00FB33F8;
+}
+
+/**
+ * pm8001_get_external_phy_settings : Retrieves the external PHY settings
+ * @pm8001_ha : our adapter
+ * @phycfg : PHY config page to populate
+ */
+static
+void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha,
+               struct pm8001_mpi3_phy_pg_trx_config *phycfg)
+{
+       phycfg->LaneLosCfg   = 0x00000132;
+       phycfg->LanePgaCfg1  = 0x00203949;
+       phycfg->LanePisoCfg1 = 0x000000FF;
+       phycfg->LanePisoCfg2 = 0xFF000001;
+       phycfg->LanePisoCfg3 = 0xE7011300;
+       phycfg->LanePisoCfg4 = 0x63349140;
+       phycfg->LanePisoCfg5 = 0xF8102036;
+       phycfg->LanePisoCfg6 = 0xF80D9300;
+       phycfg->LaneBctCtrl  = 0x00FB33F8;
+}
+
+/**
+ * pm8001_get_phy_mask : Retrieves the mask that denotes if a PHY is int/ext
+ * @pm8001_ha : our adapter
+ * @phymask : The PHY mask
+ */
+static
+void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask)
+{
+       switch (pm8001_ha->pdev->subsystem_device) {
+       case 0x0070: /* H1280 - 8 external 0 internal */
+       case 0x0072: /* H12F0 - 16 external 0 internal */
+               *phymask = 0x0000;
+               break;
+
+       case 0x0071: /* H1208 - 0 external 8 internal */
+       case 0x0073: /* H120F - 0 external 16 internal */
+               *phymask = 0xFFFF;
+               break;
+
+       case 0x0080: /* H1244 - 4 external 4 internal */
+               *phymask = 0x00F0;
+               break;
+
+       case 0x0081: /* H1248 - 4 external 8 internal */
+               *phymask = 0x0FF0;
+               break;
+
+       case 0x0082: /* H1288 - 8 external 8 internal */
+               *phymask = 0xFF00;
+               break;
+
+       default:
+               PM8001_INIT_DBG(pm8001_ha,
+                       pm8001_printk("Unknown subsystem device=0x%.04x",
+                               pm8001_ha->pdev->subsystem_device));
+       }
+}
+
+/**
+ * pm8001_set_phy_settings_ven_117c_12Gb : Configure ATTO 12Gb PHY settings
+ * @pm8001_ha : our adapter
+ */
+static
+int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha)
+{
+       struct pm8001_mpi3_phy_pg_trx_config phycfg_int;
+       struct pm8001_mpi3_phy_pg_trx_config phycfg_ext;
+       int phymask = 0;
+       int i = 0;
+
+       memset(&phycfg_int, 0, sizeof(phycfg_int));
+       memset(&phycfg_ext, 0, sizeof(phycfg_ext));
+
+       pm8001_get_internal_phy_settings(pm8001_ha, &phycfg_int);
+       pm8001_get_external_phy_settings(pm8001_ha, &phycfg_ext);
+       pm8001_get_phy_mask(pm8001_ha, &phymask);
+
+       for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+               if (phymask & (1 << i)) {/* Internal PHY */
+                       pm8001_set_phy_profile_single(pm8001_ha, i,
+                                       sizeof(phycfg_int) / sizeof(u32),
+                                       (u32 *)&phycfg_int);
+
+               } else { /* External PHY */
+                       pm8001_set_phy_profile_single(pm8001_ha, i,
+                                       sizeof(phycfg_ext) / sizeof(u32),
+                                       (u32 *)&phycfg_ext);
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * pm8001_configure_phy_settings : Configures PHY settings based on vendor ID.
+ * @pm8001_ha : our hba.
+ */
+static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha)
+{
+       switch (pm8001_ha->pdev->subsystem_vendor) {
+       case PCI_VENDOR_ID_ATTO:
+               if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */
+                       return 0;
+               else
+                       return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha);
+
+       case PCI_VENDOR_ID_ADAPTEC2:
+       case 0:
+               return 0;
+
+       default:
+               return pm8001_get_phy_settings_info(pm8001_ha);
+       }
+}
+
 #ifdef PM8001_USE_MSIX
 /**
  * pm8001_setup_msix - enable MSI-X interrupt
@@ -792,7 +951,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
        pdev = pm8001_ha->pdev;
 
 #ifdef PM8001_USE_MSIX
-       if (pdev->msix_cap)
+       if (pdev->msix_cap && pci_msi_enabled())
                return pm8001_setup_msix(pm8001_ha);
        else {
                PM8001_INIT_DBG(pm8001_ha,
@@ -803,6 +962,8 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
 
 intx:
        /* initialize the INT-X interrupt */
+       pm8001_ha->irq_vector[0].irq_id = 0;
+       pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
        rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
                DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
        return rc;
@@ -902,12 +1063,9 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 
        pm8001_init_sas_add(pm8001_ha);
        /* phy setting support for motherboard controller */
-       if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 &&
-               pdev->subsystem_vendor != 0) {
-               rc = pm8001_get_phy_settings_info(pm8001_ha);
-               if (rc)
-                       goto err_out_shost;
-       }
+       if (pm8001_configure_phy_settings(pm8001_ha))
+               goto err_out_shost;
+
        pm8001_post_sas_ha_init(shost, chip);
        rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
        if (rc)
@@ -937,10 +1095,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
        struct pm8001_hba_info *pm8001_ha;
        int i, j;
        pm8001_ha = sha->lldd_ha;
+       scsi_remove_host(pm8001_ha->shost);
        sas_unregister_ha(sha);
        sas_remove_host(pm8001_ha->shost);
        list_del(&pm8001_ha->list);
-       scsi_remove_host(pm8001_ha->shost);
        PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF);
        PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
 
@@ -956,7 +1114,8 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
 #endif
 #ifdef PM8001_USE_TASKLET
        /* For non-msix and msix interrupts */
-       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+       if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+           (pm8001_ha->chip_id == chip_8001))
                tasklet_kill(&pm8001_ha->tasklet[0]);
        else
                for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
@@ -1005,7 +1164,8 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 #endif
 #ifdef PM8001_USE_TASKLET
        /* For non-msix and msix interrupts */
-       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+       if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+           (pm8001_ha->chip_id == chip_8001))
                tasklet_kill(&pm8001_ha->tasklet[0]);
        else
                for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
@@ -1074,7 +1234,8 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
                goto err_out_disable;
 #ifdef PM8001_USE_TASKLET
        /*  Tasklet for non msi-x interrupt handler */
-       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+       if ((!pdev->msix_cap || !pci_msi_enabled()) ||
+           (pm8001_ha->chip_id == chip_8001))
                tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
                        (unsigned long)&(pm8001_ha->irq_vector[0]));
        else
@@ -1087,6 +1248,19 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
                for (i = 1; i < pm8001_ha->number_of_intr; i++)
                        PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i);
        }
+
+       /* Chip documentation for the 8070 and 8072 SPCv    */
+       /* states that a 500ms minimum delay is required    */
+       /* before issuing commands.  Otherwise, the firmare */
+       /* will enter an unrecoverable state.               */
+
+       if (pm8001_ha->chip_id == chip_8070 ||
+               pm8001_ha->chip_id == chip_8072) {
+               mdelay(500);
+       }
+
+       /* Spin up the PHYs */
+
        pm8001_ha->flags = PM8001F_RUN_TIME;
        for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
                pm8001_ha->phy[i].enable_completion = &completion;
@@ -1165,6 +1339,20 @@ static struct pci_device_id pm8001_pci_table[] = {
                PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 },
        { PCI_VENDOR_ID_ADAPTEC2, 0x8074,
                PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 },
+       { PCI_VENDOR_ID_ATTO, 0x8070,
+               PCI_VENDOR_ID_ATTO, 0x0070, 0, 0, chip_8070 },
+       { PCI_VENDOR_ID_ATTO, 0x8070,
+               PCI_VENDOR_ID_ATTO, 0x0071, 0, 0, chip_8070 },
+       { PCI_VENDOR_ID_ATTO, 0x8072,
+               PCI_VENDOR_ID_ATTO, 0x0072, 0, 0, chip_8072 },
+       { PCI_VENDOR_ID_ATTO, 0x8072,
+               PCI_VENDOR_ID_ATTO, 0x0073, 0, 0, chip_8072 },
+       { PCI_VENDOR_ID_ATTO, 0x8070,
+               PCI_VENDOR_ID_ATTO, 0x0080, 0, 0, chip_8070 },
+       { PCI_VENDOR_ID_ATTO, 0x8072,
+               PCI_VENDOR_ID_ATTO, 0x0081, 0, 0, chip_8072 },
+       { PCI_VENDOR_ID_ATTO, 0x8072,
+               PCI_VENDOR_ID_ATTO, 0x0082, 0, 0, chip_8072 },
        {} /* terminate list */
 };
 
@@ -1220,7 +1408,7 @@ MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
 MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
 MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
 MODULE_DESCRIPTION(
-               "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077 "
+               "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077/8070/8072 "
                "SAS/SATA controller driver");
 MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
index e2e97db38ae8c73e0c8f2064cb7cd5bc28932060..6628cc38316c2ef5871ef81db4d9fe772e402fee 100644 (file)
@@ -106,7 +106,9 @@ do {                                                \
 #define DEV_IS_EXPANDER(type)  ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
 #define IS_SPCV_12G(dev)       ((dev->device == 0X8074)                \
                                || (dev->device == 0X8076)              \
-                               || (dev->device == 0X8077))
+                               || (dev->device == 0X8077)              \
+                               || (dev->device == 0X8070)              \
+                               || (dev->device == 0X8072))
 
 #define PM8001_NAME_LENGTH             32/* generic length of strings */
 extern struct list_head hba_list;
@@ -708,6 +710,8 @@ int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
 int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
        u32 length, u8 *buf);
+void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
+               u32 phy, u32 length, u32 *buf);
 int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 ssize_t pm80xx_get_fatal_dump(struct device *cdev,
                struct device_attribute *attr, char *buf);
index 9a389f1508de8518cf08b0b62dee1c42251a2907..eb4fee61df729f700c8db790a632b9fe3b146324 100644 (file)
@@ -1267,6 +1267,8 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
                /* check iButton feature support for motherboard controller */
                if (pm8001_ha->pdev->subsystem_vendor !=
                        PCI_VENDOR_ID_ADAPTEC2 &&
+                       pm8001_ha->pdev->subsystem_vendor !=
+                       PCI_VENDOR_ID_ATTO &&
                        pm8001_ha->pdev->subsystem_vendor != 0) {
                        ibutton0 = pm8001_cr32(pm8001_ha, 0,
                                        MSGU_HOST_SCRATCH_PAD_6);
@@ -4576,6 +4578,38 @@ void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
        }
        PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n"));
 }
+
+void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
+               u32 phy, u32 length, u32 *buf)
+{
+       u32 tag, opc;
+       int rc, i;
+       struct set_phy_profile_req payload;
+       struct inbound_queue_table *circularQ;
+
+       memset(&payload, 0, sizeof(payload));
+
+       rc = pm8001_tag_alloc(pm8001_ha, &tag);
+       if (rc)
+               PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag"));
+
+       circularQ = &pm8001_ha->inbnd_q_tbl[0];
+       opc = OPC_INB_SET_PHY_PROFILE;
+
+       payload.tag = cpu_to_le32(tag);
+       payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8)
+                               | (phy & 0xFF));
+
+       for (i = 0; i < length; i++)
+               payload.reserved[i] = cpu_to_le32(*(buf + i));
+
+       rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+       if (rc)
+               pm8001_tag_free(pm8001_ha, tag);
+
+       PM8001_INIT_DBG(pm8001_ha,
+               pm8001_printk("PHY %d settings applied", phy));
+}
 const struct pm8001_dispatch pm8001_80xx_dispatch = {
        .name                   = "pmc80xx",
        .chip_init              = pm80xx_chip_init,
index ed31d8cc62665cf919d6b31d3bad01c275104362..b2a88200fe546b2243574b90422cb52da73b10fb 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/processor.h>
 #include <linux/libata.h>
 #include <linux/mutex.h>
+#include <linux/ktime.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
@@ -4254,7 +4255,6 @@ static struct scsi_host_template pmcraid_host_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
        .proc_name = PMCRAID_DRIVER_NAME,
-       .use_blk_tags = 1,
 };
 
 /*
@@ -5563,11 +5563,9 @@ static void pmcraid_set_timestamp(struct pmcraid_cmd *cmd)
        __be32 time_stamp_len = cpu_to_be32(PMCRAID_TIMESTAMP_LEN);
        struct pmcraid_ioadl_desc *ioadl = ioarcb->add_data.u.ioadl;
 
-       struct timeval tv;
        __le64 timestamp;
 
-       do_gettimeofday(&tv);
-       timestamp = tv.tv_sec * 1000;
+       timestamp = ktime_get_real_seconds() * 1000;
 
        pinstance->timestamp_data->timestamp[0] = (__u8)(timestamp);
        pinstance->timestamp_data->timestamp[1] = (__u8)((timestamp) >> 8);
index c2dd17b1d26fa6b275268256623a167a8682019d..bfa9a64c316b6ca2eec9a1b2277608f68101d92d 100644 (file)
@@ -267,7 +267,6 @@ struct scsi_host_template qla2xxx_driver_template = {
        .shost_attrs            = qla2x00_host_attrs,
 
        .supported_mode         = MODE_INITIATOR,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
index ac65cb7b48861b81dc1daa0ea531e506cb5752fa..3ba2e9564b9a78f000c234fa1be7bb05e24eaebd 100644 (file)
@@ -43,8 +43,6 @@
 #include <scsi/scsi_cmnd.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 
 #include "qla_def.h"
 #include "qla_target.h"
@@ -729,23 +727,23 @@ static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl,
 
 #define DEF_QLA_TPG_ATTRIB(name)                                       \
                                                                        \
-static ssize_t tcm_qla2xxx_tpg_attrib_show_##name(                     \
-       struct se_portal_group *se_tpg,                                 \
-       char *page)                                                     \
+static ssize_t tcm_qla2xxx_tpg_attrib_##name##_show(                   \
+               struct config_item *item, char *page)                   \
 {                                                                      \
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);           \
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,              \
                        struct tcm_qla2xxx_tpg, se_tpg);                \
                                                                        \
        return sprintf(page, "%u\n", tpg->tpg_attrib.name);     \
 }                                                                      \
                                                                        \
-static ssize_t tcm_qla2xxx_tpg_attrib_store_##name(                    \
-       struct se_portal_group *se_tpg,                                 \
-       const char *page,                                               \
-       size_t count)                                                   \
+static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store(                  \
+               struct config_item *item, const char *page, size_t count) \
 {                                                                      \
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);           \
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,              \
                        struct tcm_qla2xxx_tpg, se_tpg);                \
+       struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib;            \
        unsigned long val;                                              \
        int ret;                                                        \
                                                                        \
@@ -755,81 +753,39 @@ static ssize_t tcm_qla2xxx_tpg_attrib_store_##name(                       \
                                " ret: %d\n", ret);                     \
                return -EINVAL;                                         \
        }                                                               \
-       ret = tcm_qla2xxx_set_attrib_##name(tpg, val);                  \
-                                                                       \
-       return (!ret) ? count : -EINVAL;                                \
-}
-
-#define DEF_QLA_TPG_ATTR_BOOL(_name)                                   \
-                                                                       \
-static int tcm_qla2xxx_set_attrib_##_name(                             \
-       struct tcm_qla2xxx_tpg *tpg,                                    \
-       unsigned long val)                                              \
-{                                                                      \
-       struct tcm_qla2xxx_tpg_attrib *a = &tpg->tpg_attrib;            \
                                                                        \
        if ((val != 0) && (val != 1)) {                                 \
                pr_err("Illegal boolean value %lu\n", val);             \
                return -EINVAL;                                         \
        }                                                               \
                                                                        \
-       a->_name = val;                                                 \
-       return 0;                                                       \
-}
-
-#define QLA_TPG_ATTR(_name, _mode) \
-       TF_TPG_ATTRIB_ATTR(tcm_qla2xxx, _name, _mode);
+       a->name = val;                                                  \
+                                                                       \
+       return count;                                                   \
+}                                                                      \
+CONFIGFS_ATTR(tcm_qla2xxx_tpg_attrib_, name)
 
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_generate_node_acls
- */
-DEF_QLA_TPG_ATTR_BOOL(generate_node_acls);
 DEF_QLA_TPG_ATTRIB(generate_node_acls);
-QLA_TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR);
-
-/*
- Define tcm_qla2xxx_attrib_s_cache_dynamic_acls
- */
-DEF_QLA_TPG_ATTR_BOOL(cache_dynamic_acls);
 DEF_QLA_TPG_ATTRIB(cache_dynamic_acls);
-QLA_TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_write_protect
- */
-DEF_QLA_TPG_ATTR_BOOL(demo_mode_write_protect);
 DEF_QLA_TPG_ATTRIB(demo_mode_write_protect);
-QLA_TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_prod_mode_write_protect
- */
-DEF_QLA_TPG_ATTR_BOOL(prod_mode_write_protect);
 DEF_QLA_TPG_ATTRIB(prod_mode_write_protect);
-QLA_TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
-
-/*
- * Define tcm_qla2xxx_tpg_attrib_s_demo_mode_login_only
- */
-DEF_QLA_TPG_ATTR_BOOL(demo_mode_login_only);
 DEF_QLA_TPG_ATTRIB(demo_mode_login_only);
-QLA_TPG_ATTR(demo_mode_login_only, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *tcm_qla2xxx_tpg_attrib_attrs[] = {
-       &tcm_qla2xxx_tpg_attrib_generate_node_acls.attr,
-       &tcm_qla2xxx_tpg_attrib_cache_dynamic_acls.attr,
-       &tcm_qla2xxx_tpg_attrib_demo_mode_write_protect.attr,
-       &tcm_qla2xxx_tpg_attrib_prod_mode_write_protect.attr,
-       &tcm_qla2xxx_tpg_attrib_demo_mode_login_only.attr,
+       &tcm_qla2xxx_tpg_attrib_attr_generate_node_acls,
+       &tcm_qla2xxx_tpg_attrib_attr_cache_dynamic_acls,
+       &tcm_qla2xxx_tpg_attrib_attr_demo_mode_write_protect,
+       &tcm_qla2xxx_tpg_attrib_attr_prod_mode_write_protect,
+       &tcm_qla2xxx_tpg_attrib_attr_demo_mode_login_only,
        NULL,
 };
 
 /* End items for tcm_qla2xxx_tpg_attrib_cit */
 
-static ssize_t tcm_qla2xxx_tpg_show_enable(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_qla2xxx_tpg_enable_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                        struct tcm_qla2xxx_tpg, se_tpg);
 
@@ -865,11 +821,10 @@ static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
        complete(&base_tpg->tpg_base_comp);
 }
 
-static ssize_t tcm_qla2xxx_tpg_store_enable(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_qla2xxx_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                        struct tcm_qla2xxx_tpg, se_tpg);
        unsigned long op;
@@ -909,22 +864,16 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
        return count;
 }
 
-TF_TPG_BASE_ATTR(tcm_qla2xxx, enable, S_IRUGO | S_IWUSR);
-
-static ssize_t tcm_qla2xxx_tpg_show_dynamic_sessions(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_qla2xxx_tpg_dynamic_sessions_show(struct config_item *item,
+               char *page)
 {
-       return target_show_dynamic_sessions(se_tpg, page);
+       return target_show_dynamic_sessions(to_tpg(item), page);
 }
 
-TF_TPG_BASE_ATTR_RO(tcm_qla2xxx, dynamic_sessions);
-
-static ssize_t tcm_qla2xxx_tpg_store_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                                struct tcm_qla2xxx_tpg, se_tpg);
        unsigned long val;
@@ -943,21 +892,24 @@ static ssize_t tcm_qla2xxx_tpg_store_fabric_prot_type(
        return count;
 }
 
-static ssize_t tcm_qla2xxx_tpg_show_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
                                struct tcm_qla2xxx_tpg, se_tpg);
 
        return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
 }
-TF_TPG_BASE_ATTR(tcm_qla2xxx, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR_WO(tcm_qla2xxx_tpg_, enable);
+CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions);
+CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type);
 
 static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = {
-       &tcm_qla2xxx_tpg_enable.attr,
-       &tcm_qla2xxx_tpg_dynamic_sessions.attr,
-       &tcm_qla2xxx_tpg_fabric_prot_type.attr,
+       &tcm_qla2xxx_tpg_attr_enable,
+       &tcm_qla2xxx_tpg_attr_dynamic_sessions,
+       &tcm_qla2xxx_tpg_attr_fabric_prot_type,
        NULL,
 };
 
@@ -1030,18 +982,16 @@ static void tcm_qla2xxx_drop_tpg(struct se_portal_group *se_tpg)
        kfree(tpg);
 }
 
-static ssize_t tcm_qla2xxx_npiv_tpg_show_enable(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_qla2xxx_npiv_tpg_enable_show(struct config_item *item,
+               char *page)
 {
-       return tcm_qla2xxx_tpg_show_enable(se_tpg, page);
+       return tcm_qla2xxx_tpg_enable_show(item, page);
 }
 
-static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_qla2xxx_npiv_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
        struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
                        struct tcm_qla2xxx_lport, lport_wwn);
@@ -1077,10 +1027,10 @@ static ssize_t tcm_qla2xxx_npiv_tpg_store_enable(
        return count;
 }
 
-TF_TPG_BASE_ATTR(tcm_qla2xxx_npiv, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_qla2xxx_npiv_tpg_, enable);
 
 static struct configfs_attribute *tcm_qla2xxx_npiv_tpg_attrs[] = {
-        &tcm_qla2xxx_npiv_tpg_enable.attr,
+        &tcm_qla2xxx_npiv_tpg_attr_enable,
         NULL,
 };
 
@@ -1783,9 +1733,8 @@ static void tcm_qla2xxx_npiv_drop_lport(struct se_wwn *wwn)
 }
 
 
-static ssize_t tcm_qla2xxx_wwn_show_attr_version(
-       struct target_fabric_configfs *tf,
-       char *page)
+static ssize_t tcm_qla2xxx_wwn_version_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page,
            "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on "
@@ -1793,10 +1742,10 @@ static ssize_t tcm_qla2xxx_wwn_show_attr_version(
            utsname()->machine);
 }
 
-TF_WWN_ATTR_RO(tcm_qla2xxx, version);
+CONFIGFS_ATTR_RO(tcm_qla2xxx_wwn_, version);
 
 static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = {
-       &tcm_qla2xxx_wwn_version.attr,
+       &tcm_qla2xxx_wwn_attr_version,
        NULL,
 };
 
index 6d25879d87c8550893cdd8671db68d542cde64cb..01c3610a60cf0b767f7566fc97967158f5eeb618 100644 (file)
@@ -212,7 +212,6 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .shost_attrs            = qla4xxx_host_attrs,
        .host_reset             = qla4xxx_host_reset,
        .vendor_id              = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
-       .use_blk_tags           = 1,
 };
 
 static struct iscsi_transport qla4xxx_iscsi_transport = {
@@ -8697,13 +8696,6 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev,
        host->can_queue = MAX_SRBS ;
        host->transportt = qla4xxx_scsi_transport;
 
-       ret = scsi_init_shared_tag_map(host, MAX_SRBS);
-       if (ret) {
-               ql4_printk(KERN_WARNING, ha,
-                          "%s: scsi_init_shared_tag_map failed\n", __func__);
-               goto probe_failed;
-       }
-
        pci_set_drvdata(pdev, ha);
 
        ret = scsi_add_host(host, &pdev->dev);
index 207d6a7a1bd0bce29ca748c8f3a4cd2aee6ad97a..d07fb653f5dc3348c41bbc68597489d2c4b25180 100644 (file)
@@ -616,32 +616,11 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
  */
 int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
 {
-       unsigned long flags;
-
-       if (depth <= 0)
-               goto out;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-
-       /*
-        * Check to see if the queue is managed by the block layer.
-        * If it is, and we fail to adjust the depth, exit.
-        *
-        * Do not resize the tag map if it is a host wide share bqt,
-        * because the size should be the hosts's can_queue. If there
-        * is more IO than the LLD's can_queue (so there are not enuogh
-        * tags) request_fn's host queue ready check will handle it.
-        */
-       if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
-               if (blk_queue_tagged(sdev->request_queue) &&
-                   blk_queue_resize_tags(sdev->request_queue, depth) != 0)
-                       goto out_unlock;
+       if (depth > 0) {
+               sdev->queue_depth = depth;
+               wmb();
        }
 
-       sdev->queue_depth = depth;
-out_unlock:
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-out:
        return sdev->queue_depth;
 }
 EXPORT_SYMBOL(scsi_change_queue_depth);
index f9f3f8203d42709d9957aa27b1be471acb612046..83245391e956bc6f351a668473debeba6121b71b 100644 (file)
@@ -55,6 +55,7 @@
  * Default timeout
  */
 #define SCSI_TIMEOUT (2*HZ)
+#define SCSI_REPORT_LUNS_TIMEOUT (30*HZ)
 
 /*
  * Prefix values for the SCSI id's (stored in sysfs name field)
@@ -274,8 +275,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
        sdev->request_queue->queuedata = sdev;
 
-       if (!shost_use_blk_mq(sdev->host) &&
-           (shost->bqt || shost->hostt->use_blk_tags)) {
+       if (!shost_use_blk_mq(sdev->host)) {
                blk_queue_init_tags(sdev->request_queue,
                                    sdev->host->cmd_per_lun, shost->bqt,
                                    shost->hostt->tag_alloc_policy);
@@ -1383,7 +1383,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
 
                result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE,
                                          lun_data, length, &sshdr,
-                                         SCSI_TIMEOUT + 4 * HZ, 3, NULL);
+                                         SCSI_REPORT_LUNS_TIMEOUT, 3, NULL);
 
                SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev,
                                "scsi scan: REPORT LUNS"
@@ -1712,8 +1712,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
                return NULL;
 
        if (shost->async_scan) {
-               shost_printk(KERN_INFO, shost, "%s called twice\n", __func__);
-               dump_stack();
+               shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
                return NULL;
        }
 
index dff8fafb741c1bff625131e73e7fe4425375ced2..8d2312239ae0cda01238ae549f0ae8007de233ea 100644 (file)
@@ -775,6 +775,29 @@ static struct bin_attribute dev_attr_vpd_##_page = {               \
 sdev_vpd_pg_attr(pg83);
 sdev_vpd_pg_attr(pg80);
 
+static ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
+                           struct bin_attribute *bin_attr,
+                           char *buf, loff_t off, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       if (!sdev->inquiry)
+               return -EINVAL;
+
+       return memory_read_from_buffer(buf, count, &off, sdev->inquiry,
+                                      sdev->inquiry_len);
+}
+
+static struct bin_attribute dev_attr_inquiry = {
+       .attr = {
+               .name = "inquiry",
+               .mode = S_IRUGO,
+       },
+       .size = 0,
+       .read = show_inquiry,
+};
+
 static ssize_t
 show_iostat_counterbits(struct device *dev, struct device_attribute *attr,
                        char *buf)
@@ -900,7 +923,7 @@ sdev_store_queue_ramp_up_period(struct device *dev,
                return -EINVAL;
 
        sdev->queue_ramp_up_period = msecs_to_jiffies(period);
-       return period;
+       return count;
 }
 
 static DEVICE_ATTR(queue_ramp_up_period, S_IRUGO | S_IWUSR,
@@ -959,6 +982,7 @@ static struct attribute *scsi_sdev_attrs[] = {
 static struct bin_attribute *scsi_sdev_bin_attrs[] = {
        &dev_attr_vpd_pg83,
        &dev_attr_vpd_pg80,
+       &dev_attr_inquiry,
        NULL
 };
 static struct attribute_group scsi_sdev_attr_group = {
@@ -1086,9 +1110,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
                device_unregister(&sdev->sdev_dev);
                transport_remove_device(dev);
                scsi_dh_remove_device(sdev);
-               device_del(dev);
-       } else
-               put_device(&sdev->sdev_dev);
+       }
 
        /*
         * Stop accepting new requests and wait until all queuecommand() and
@@ -1099,6 +1121,16 @@ void __scsi_remove_device(struct scsi_device *sdev)
        blk_cleanup_queue(sdev->request_queue);
        cancel_work_sync(&sdev->requeue_work);
 
+       /*
+        * Remove the device after blk_cleanup_queue() has been called such
+        * a possible bdi_register() call with the same name occurs after
+        * blk_cleanup_queue() has called bdi_destroy().
+        */
+       if (sdev->is_visible)
+               device_del(dev);
+       else
+               put_device(&sdev->sdev_dev);
+
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(dev);
@@ -1160,31 +1192,23 @@ static void __scsi_remove_target(struct scsi_target *starget)
 void scsi_remove_target(struct device *dev)
 {
        struct Scsi_Host *shost = dev_to_shost(dev->parent);
-       struct scsi_target *starget, *last = NULL;
+       struct scsi_target *starget;
        unsigned long flags;
 
-       /* remove targets being careful to lookup next entry before
-        * deleting the last
-        */
+restart:
        spin_lock_irqsave(shost->host_lock, flags);
        list_for_each_entry(starget, &shost->__targets, siblings) {
                if (starget->state == STARGET_DEL)
                        continue;
                if (starget->dev.parent == dev || &starget->dev == dev) {
-                       /* assuming new targets arrive at the end */
                        kref_get(&starget->reap_ref);
                        spin_unlock_irqrestore(shost->host_lock, flags);
-                       if (last)
-                               scsi_target_reap(last);
-                       last = starget;
                        __scsi_remove_target(starget);
-                       spin_lock_irqsave(shost->host_lock, flags);
+                       scsi_target_reap(starget);
+                       goto restart;
                }
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
-
-       if (last)
-               scsi_target_reap(last);
 }
 EXPORT_SYMBOL(scsi_remove_target);
 
index 5e170a6809fde2fe3c8c6ff51d382c2a570485ea..54519804c46a57b99ce680ee665b4fe28dd91148 100644 (file)
@@ -205,6 +205,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
        buffer_data[2] &= ~0x05;
        buffer_data[2] |= wce << 2 | rcd;
        sp = buffer_data[0] & 0x80 ? 1 : 0;
+       buffer_data[0] &= ~0x80;
 
        if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
                             SD_MAX_RETRIES, &data, &sshdr)) {
index 9d7b7db75e4b96b6fbb33bf24b91c205add07d79..503ab8b46c0b4e8a73d7e826ba1aaf3be1abd6b0 100644 (file)
@@ -787,8 +787,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
                return k;       /* probably out of space --> ENOMEM */
        }
        if (atomic_read(&sdp->detaching)) {
-               if (srp->bio)
+               if (srp->bio) {
+                       if (srp->rq->cmd != srp->rq->__cmd)
+                               kfree(srp->rq->cmd);
+
                        blk_end_request_all(srp->rq, -EIO);
+                       srp->rq = NULL;
+               }
+
                sg_finish_rem_req(srp);
                return -ENODEV;
        }
index b2b87cef00fcce3c2f765a71cd7020f7c5790e32..2b3c25371d769e4626c6c91898a848c1f995def4 100644 (file)
@@ -124,7 +124,6 @@ static struct scsi_host_template snic_host_template = {
        .sg_tablesize = SNIC_MAX_SG_DESC_CNT,
        .max_sectors = 0x800,
        .shost_attrs = snic_attrs,
-       .use_blk_tags = 1,
        .track_queue_depth = 1,
        .cmd_size = sizeof(struct snic_internal_io_state),
        .proc_name = "snic_scsi",
@@ -533,15 +532,6 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        snic->max_tag_id = shost->can_queue;
 
-       ret = scsi_init_shared_tag_map(shost, snic->max_tag_id);
-       if (ret) {
-               SNIC_HOST_ERR(shost,
-                             "Unable to alloc shared tag map. %d\n",
-                             ret);
-
-               goto err_dev_close;
-       }
-
        shost->max_lun = snic->config.luns_per_tgt;
        shost->max_id = SNIC_MAX_TARGET;
 
index b37b9b00c4b460ca97b44720d5aee1405c2d89ef..e0a1e52a04e736b35dc2b03371a72fc0590b85b1 100644 (file)
@@ -4452,11 +4452,41 @@ static ssize_t version_show(struct device_driver *ddd, char *buf)
 }
 static DRIVER_ATTR_RO(version);
 
+#if DEBUG
+static ssize_t debug_flag_store(struct device_driver *ddp,
+       const char *buf, size_t count)
+{
+/* We only care what the first byte of the data is the rest is unused.
+ * if it's a '1' we turn on debug and if it's a '0' we disable it. All
+ * other values have -EINVAL returned if they are passed in.
+ */
+       if (count > 0) {
+               if (buf[0] == '0') {
+                       debugging = NO_DEBUG;
+                       return count;
+               } else if (buf[0] == '1') {
+                       debugging = 1;
+                       return count;
+               }
+       }
+       return -EINVAL;
+}
+
+static ssize_t debug_flag_show(struct device_driver *ddp, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%d\n", debugging);
+}
+static DRIVER_ATTR_RW(debug_flag);
+#endif
+
 static struct attribute *st_drv_attrs[] = {
        &driver_attr_try_direct_io.attr,
        &driver_attr_fixed_buffer_size.attr,
        &driver_attr_max_sg_segs.attr,
        &driver_attr_version.attr,
+#if DEBUG
+       &driver_attr_debug_flag.attr,
+#endif
        NULL,
 };
 ATTRIBUTE_GROUPS(st_drv);
index 98a62bc15069773ba2de93dd9d4164e8655919f0..2de28d7a0b045e6e88a7256f1ac3e0a5324c4541 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/ktime.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
@@ -362,14 +363,6 @@ MODULE_DESCRIPTION("Promise Technology SuperTrak EX Controllers");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ST_DRIVER_VERSION);
 
-static void stex_gettime(__le64 *time)
-{
-       struct timeval tv;
-
-       do_gettimeofday(&tv);
-       *time = cpu_to_le64(tv.tv_sec);
-}
-
 static struct status_msg *stex_get_status(struct st_hba *hba)
 {
        struct status_msg *status = hba->status_buffer + hba->status_tail;
@@ -1002,7 +995,7 @@ static int stex_common_handshake(struct st_hba *hba)
        h->req_cnt = cpu_to_le16(hba->rq_count+1);
        h->status_sz = cpu_to_le16(sizeof(struct status_msg));
        h->status_cnt = cpu_to_le16(hba->sts_count+1);
-       stex_gettime(&h->hosttime);
+       h->hosttime = cpu_to_le64(ktime_get_real_seconds());
        h->partner_type = HMU_PARTNER_TYPE;
        if (hba->extra_offset) {
                h->extra_offset = cpu_to_le32(hba->extra_offset);
@@ -1076,7 +1069,7 @@ static int stex_ss_handshake(struct st_hba *hba)
        h->req_cnt = cpu_to_le16(hba->rq_count+1);
        h->status_sz = cpu_to_le16(sizeof(struct status_msg));
        h->status_cnt = cpu_to_le16(hba->sts_count+1);
-       stex_gettime(&h->hosttime);
+       h->hosttime = cpu_to_le64(ktime_get_real_seconds());
        h->partner_type = HMU_PARTNER_TYPE;
        h->extra_offset = h->extra_size = 0;
        scratch_size = (hba->sts_count+1)*sizeof(u32);
@@ -1374,7 +1367,6 @@ static struct scsi_host_template driver_template = {
        .eh_abort_handler               = stex_abort,
        .eh_host_reset_handler          = stex_reset,
        .this_id                        = -1,
-       .use_blk_tags                   = 1,
 };
 
 static struct pci_device_id stex_pci_tbl[] = {
@@ -1659,13 +1651,6 @@ static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (err)
                goto out_free_irq;
 
-       err = scsi_init_shared_tag_map(host, host->can_queue);
-       if (err) {
-               printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n",
-                       pci_name(pdev));
-               goto out_free_irq;
-       }
-
        pci_set_drvdata(pdev, hba);
 
        err = scsi_add_host(host, &pdev->dev);
index 40c43aeb4ff364898f160d7528d93ea4ef46a00a..3fba42ad9fb8aee55d5015167a9cb9ad601fb1a7 100644 (file)
@@ -349,11 +349,14 @@ enum storvsc_request_type {
  */
 
 #define SRB_STATUS_AUTOSENSE_VALID     0x80
+#define SRB_STATUS_QUEUE_FROZEN                0x40
 #define SRB_STATUS_INVALID_LUN 0x20
 #define SRB_STATUS_SUCCESS     0x01
 #define SRB_STATUS_ABORTED     0x02
 #define SRB_STATUS_ERROR       0x04
 
+#define SRB_STATUS(status) \
+       (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
 /*
  * This is the end of Protocol specific defines.
  */
@@ -393,9 +396,6 @@ static void storvsc_on_channel_callback(void *context);
 struct storvsc_cmd_request {
        struct scsi_cmnd *cmd;
 
-       unsigned int bounce_sgl_count;
-       struct scatterlist *bounce_sgl;
-
        struct hv_device *device;
 
        /* Synchronize the request/response if needed */
@@ -586,241 +586,6 @@ static inline struct storvsc_device *get_in_stor_device(
 
 }
 
-static void destroy_bounce_buffer(struct scatterlist *sgl,
-                                 unsigned int sg_count)
-{
-       int i;
-       struct page *page_buf;
-
-       for (i = 0; i < sg_count; i++) {
-               page_buf = sg_page((&sgl[i]));
-               if (page_buf != NULL)
-                       __free_page(page_buf);
-       }
-
-       kfree(sgl);
-}
-
-static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
-{
-       int i;
-
-       /* No need to check */
-       if (sg_count < 2)
-               return -1;
-
-       /* We have at least 2 sg entries */
-       for (i = 0; i < sg_count; i++) {
-               if (i == 0) {
-                       /* make sure 1st one does not have hole */
-                       if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
-                               return i;
-               } else if (i == sg_count - 1) {
-                       /* make sure last one does not have hole */
-                       if (sgl[i].offset != 0)
-                               return i;
-               } else {
-                       /* make sure no hole in the middle */
-                       if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
-                               return i;
-               }
-       }
-       return -1;
-}
-
-static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
-                                               unsigned int sg_count,
-                                               unsigned int len,
-                                               int write)
-{
-       int i;
-       int num_pages;
-       struct scatterlist *bounce_sgl;
-       struct page *page_buf;
-       unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
-
-       num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
-
-       bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
-       if (!bounce_sgl)
-               return NULL;
-
-       sg_init_table(bounce_sgl, num_pages);
-       for (i = 0; i < num_pages; i++) {
-               page_buf = alloc_page(GFP_ATOMIC);
-               if (!page_buf)
-                       goto cleanup;
-               sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
-       }
-
-       return bounce_sgl;
-
-cleanup:
-       destroy_bounce_buffer(bounce_sgl, num_pages);
-       return NULL;
-}
-
-/* Assume the original sgl has enough room */
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
-                                           struct scatterlist *bounce_sgl,
-                                           unsigned int orig_sgl_count,
-                                           unsigned int bounce_sgl_count)
-{
-       int i;
-       int j = 0;
-       unsigned long src, dest;
-       unsigned int srclen, destlen, copylen;
-       unsigned int total_copied = 0;
-       unsigned long bounce_addr = 0;
-       unsigned long dest_addr = 0;
-       unsigned long flags;
-       struct scatterlist *cur_dest_sgl;
-       struct scatterlist *cur_src_sgl;
-
-       local_irq_save(flags);
-       cur_dest_sgl = orig_sgl;
-       cur_src_sgl = bounce_sgl;
-       for (i = 0; i < orig_sgl_count; i++) {
-               dest_addr = (unsigned long)
-                               kmap_atomic(sg_page(cur_dest_sgl)) +
-                               cur_dest_sgl->offset;
-               dest = dest_addr;
-               destlen = cur_dest_sgl->length;
-
-               if (bounce_addr == 0)
-                       bounce_addr = (unsigned long)kmap_atomic(
-                                                       sg_page(cur_src_sgl));
-
-               while (destlen) {
-                       src = bounce_addr + cur_src_sgl->offset;
-                       srclen = cur_src_sgl->length - cur_src_sgl->offset;
-
-                       copylen = min(srclen, destlen);
-                       memcpy((void *)dest, (void *)src, copylen);
-
-                       total_copied += copylen;
-                       cur_src_sgl->offset += copylen;
-                       destlen -= copylen;
-                       dest += copylen;
-
-                       if (cur_src_sgl->offset == cur_src_sgl->length) {
-                               /* full */
-                               kunmap_atomic((void *)bounce_addr);
-                               j++;
-
-                               /*
-                                * It is possible that the number of elements
-                                * in the bounce buffer may not be equal to
-                                * the number of elements in the original
-                                * scatter list. Handle this correctly.
-                                */
-
-                               if (j == bounce_sgl_count) {
-                                       /*
-                                        * We are done; cleanup and return.
-                                        */
-                                       kunmap_atomic((void *)(dest_addr -
-                                               cur_dest_sgl->offset));
-                                       local_irq_restore(flags);
-                                       return total_copied;
-                               }
-
-                               /* if we need to use another bounce buffer */
-                               if (destlen || i != orig_sgl_count - 1) {
-                                       cur_src_sgl = sg_next(cur_src_sgl);
-                                       bounce_addr = (unsigned long)
-                                                       kmap_atomic(
-                                                       sg_page(cur_src_sgl));
-                               }
-                       } else if (destlen == 0 && i == orig_sgl_count - 1) {
-                               /* unmap the last bounce that is < PAGE_SIZE */
-                               kunmap_atomic((void *)bounce_addr);
-                       }
-               }
-
-               kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset));
-               cur_dest_sgl = sg_next(cur_dest_sgl);
-       }
-
-       local_irq_restore(flags);
-
-       return total_copied;
-}
-
-/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
-static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
-                                         struct scatterlist *bounce_sgl,
-                                         unsigned int orig_sgl_count)
-{
-       int i;
-       int j = 0;
-       unsigned long src, dest;
-       unsigned int srclen, destlen, copylen;
-       unsigned int total_copied = 0;
-       unsigned long bounce_addr = 0;
-       unsigned long src_addr = 0;
-       unsigned long flags;
-       struct scatterlist *cur_src_sgl;
-       struct scatterlist *cur_dest_sgl;
-
-       local_irq_save(flags);
-
-       cur_src_sgl = orig_sgl;
-       cur_dest_sgl = bounce_sgl;
-
-       for (i = 0; i < orig_sgl_count; i++) {
-               src_addr = (unsigned long)
-                               kmap_atomic(sg_page(cur_src_sgl)) +
-                               cur_src_sgl->offset;
-               src = src_addr;
-               srclen = cur_src_sgl->length;
-
-               if (bounce_addr == 0)
-                       bounce_addr = (unsigned long)
-                                       kmap_atomic(sg_page(cur_dest_sgl));
-
-               while (srclen) {
-                       /* assume bounce offset always == 0 */
-                       dest = bounce_addr + cur_dest_sgl->length;
-                       destlen = PAGE_SIZE - cur_dest_sgl->length;
-
-                       copylen = min(srclen, destlen);
-                       memcpy((void *)dest, (void *)src, copylen);
-
-                       total_copied += copylen;
-                       cur_dest_sgl->length += copylen;
-                       srclen -= copylen;
-                       src += copylen;
-
-                       if (cur_dest_sgl->length == PAGE_SIZE) {
-                               /* full..move to next entry */
-                               kunmap_atomic((void *)bounce_addr);
-                               bounce_addr = 0;
-                               j++;
-                       }
-
-                       /* if we need to use another bounce buffer */
-                       if (srclen && bounce_addr == 0) {
-                               cur_dest_sgl = sg_next(cur_dest_sgl);
-                               bounce_addr = (unsigned long)
-                                               kmap_atomic(
-                                               sg_page(cur_dest_sgl));
-                       }
-
-               }
-
-               kunmap_atomic((void *)(src_addr - cur_src_sgl->offset));
-               cur_src_sgl = sg_next(cur_src_sgl);
-       }
-
-       if (bounce_addr)
-               kunmap_atomic((void *)bounce_addr);
-
-       local_irq_restore(flags);
-
-       return total_copied;
-}
-
 static void handle_sc_creation(struct vmbus_channel *new_sc)
 {
        struct hv_device *device = new_sc->primary_channel->device_obj;
@@ -1096,7 +861,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
        void (*process_err_fn)(struct work_struct *work);
        bool do_work = false;
 
-       switch (vm_srb->srb_status) {
+       switch (SRB_STATUS(vm_srb->srb_status)) {
        case SRB_STATUS_ERROR:
                /*
                 * If there is an error; offline the device since all
@@ -1171,15 +936,6 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        host = stor_dev->host;
 
        vm_srb = &cmd_request->vstor_packet.vm_srb;
-       if (cmd_request->bounce_sgl_count) {
-               if (vm_srb->data_in == READ_TYPE)
-                       copy_from_bounce_buffer(scsi_sglist(scmnd),
-                                       cmd_request->bounce_sgl,
-                                       scsi_sg_count(scmnd),
-                                       cmd_request->bounce_sgl_count);
-               destroy_bounce_buffer(cmd_request->bounce_sgl,
-                                       cmd_request->bounce_sgl_count);
-       }
 
        scmnd->result = vm_srb->scsi_status;
 
@@ -1474,6 +1230,9 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
 
        blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ));
 
+       /* Ensure there are no gaps in presented sgls */
+       blk_queue_virt_boundary(sdevice->request_queue, PAGE_SIZE - 1);
+
        sdevice->no_write_same = 1;
 
        /*
@@ -1647,8 +1406,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        vm_srb->win8_extension.time_out_value = 60;
 
        vm_srb->win8_extension.srb_flags |=
-               (SRB_FLAGS_QUEUE_ACTION_ENABLE |
-               SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
+               SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
 
        /* Build the SRB */
        switch (scmnd->sc_data_direction) {
@@ -1692,40 +1450,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        payload_sz = sizeof(cmd_request->mpb);
 
        if (sg_count) {
-               /* check if we need to bounce the sgl */
-               if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
-                       cmd_request->bounce_sgl =
-                               create_bounce_buffer(sgl, sg_count,
-                                                    length,
-                                                    vm_srb->data_in);
-                       if (!cmd_request->bounce_sgl)
-                               return SCSI_MLQUEUE_HOST_BUSY;
-
-                       cmd_request->bounce_sgl_count =
-                               ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT;
-
-                       if (vm_srb->data_in == WRITE_TYPE)
-                               copy_to_bounce_buffer(sgl,
-                                       cmd_request->bounce_sgl, sg_count);
-
-                       sgl = cmd_request->bounce_sgl;
-                       sg_count = cmd_request->bounce_sgl_count;
-               }
-
-
                if (sg_count > MAX_PAGE_BUFFER_COUNT) {
 
                        payload_sz = (sg_count * sizeof(void *) +
                                      sizeof(struct vmbus_packet_mpb_array));
                        payload = kmalloc(payload_sz, GFP_ATOMIC);
-                       if (!payload) {
-                               if (cmd_request->bounce_sgl_count)
-                                       destroy_bounce_buffer(
-                                       cmd_request->bounce_sgl,
-                                       cmd_request->bounce_sgl_count);
-
-                                       return SCSI_MLQUEUE_DEVICE_BUSY;
-                       }
+                       if (!payload)
+                               return SCSI_MLQUEUE_DEVICE_BUSY;
                }
 
                payload->range.len = length;
@@ -1754,11 +1485,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
 
        if (ret == -EAGAIN) {
                /* no more space */
-
-               if (cmd_request->bounce_sgl_count)
-                       destroy_bounce_buffer(cmd_request->bounce_sgl,
-                                       cmd_request->bounce_sgl_count);
-
                return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
index e94538362536e4234b180201c7a70ae21bde7af1..5f4530744e0af7bd1ea8e4ca76fffe3a87d11d56 100644 (file)
@@ -72,7 +72,7 @@ config SCSI_UFSHCD_PLATFORM
          If unsure, say N.
 
 config SCSI_UFS_QCOM
-       bool "QCOM specific hooks to UFS controller platform driver"
+       tristate "QCOM specific hooks to UFS controller platform driver"
        depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
        select PHY_QCOM_UFS
        help
index 4cdffa46d401a5ea6120ba5d350e453158166a31..4f38d008bfb401d9eeeb359472e643bdf3e85c9b 100644 (file)
 
 #include <linux/phy/phy-qcom-ufs.h>
 #include "ufshcd.h"
+#include "ufshcd-pltfrm.h"
 #include "unipro.h"
 #include "ufs-qcom.h"
 #include "ufshci.h"
+#define UFS_QCOM_DEFAULT_DBG_PRINT_EN  \
+       (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+
+enum {
+       TSTBUS_UAWM,
+       TSTBUS_UARM,
+       TSTBUS_TXUC,
+       TSTBUS_RXUC,
+       TSTBUS_DFC,
+       TSTBUS_TRLUT,
+       TSTBUS_TMRLUT,
+       TSTBUS_OCSC,
+       TSTBUS_UTP_HCI,
+       TSTBUS_COMBINED,
+       TSTBUS_WRAPPER,
+       TSTBUS_UNIPRO,
+       TSTBUS_MAX,
+};
 
 static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
 
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
-               const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
+static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
+static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
+                                                      u32 clk_cycles);
+
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+               char *prefix)
+{
+       print_hex_dump(KERN_ERR, prefix,
+                       len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+                       16, 4, (void __force *)hba->mmio_base + offset,
+                       len * 4, false);
+}
 
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
@@ -149,13 +177,14 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host)
 
        err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
                &host->tx_l1_sync_clk);
+
 out:
        return err;
 }
 
 static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct phy *phy = host->generic_phy;
        u32 tx_lanes;
        int err = 0;
@@ -181,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
 
        do {
                err = ufshcd_dme_get(hba,
-                       UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val);
+                               UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+                                       UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+                               &tx_fsm_val);
                if (err || tx_fsm_val == TX_FSM_HIBERN8)
                        break;
 
@@ -195,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
         */
        if (time_after(jiffies, timeout))
                err = ufshcd_dme_get(hba,
-                               UIC_ARG_MIB(MPHY_TX_FSM_STATE), &tx_fsm_val);
+                               UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+                                       UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+                               &tx_fsm_val);
 
        if (err) {
                dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
@@ -209,9 +242,18 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
        return err;
 }
 
+static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
+{
+       ufshcd_rmwl(host->hba, QUNIPRO_SEL,
+                  ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
+                  REG_UFS_CFG1);
+       /* make sure above configuration is applied before we return */
+       mb();
+}
+
 static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct phy *phy = host->generic_phy;
        int ret = 0;
        bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
@@ -223,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
        usleep_range(1000, 1100);
 
        ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
+
        if (ret) {
-               dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n",
-                       __func__, ret);
+               dev_err(hba->dev,
+               "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
+               __func__, ret);
                goto out;
        }
 
@@ -246,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 
        ret = ufs_qcom_phy_is_pcs_ready(phy);
        if (ret)
-               dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n",
+               dev_err(hba->dev,
+                       "%s: is_physical_coding_sublayer_ready() failed, ret = %d\n",
                        __func__, ret);
 
+       ufs_qcom_select_unipro_mode(host);
+
 out:
        return ret;
 }
@@ -271,9 +318,10 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
        mb();
 }
 
-static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
+static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
+                                     enum ufs_notify_change_status status)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        int err = 0;
 
        switch (status) {
@@ -301,13 +349,13 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
 }
 
 /**
- * Returns non-zero for success (which rate of core_clk) and 0
- * in case of a failure
+ * Returns zero for success and non-zero in case of a failure
  */
-static unsigned long
-ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
+static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
+                              u32 hs, u32 rate, bool update_link_startup_timer)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       int ret = 0;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct ufs_clk_info *clki;
        u32 core_clk_period_in_ns;
        u32 tx_clk_cycles_per_us = 0;
@@ -324,11 +372,13 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
        static u32 hs_fr_table_rA[][2] = {
                {UFS_HS_G1, 0x1F},
                {UFS_HS_G2, 0x3e},
+               {UFS_HS_G3, 0x7D},
        };
 
        static u32 hs_fr_table_rB[][2] = {
                {UFS_HS_G1, 0x24},
                {UFS_HS_G2, 0x49},
+               {UFS_HS_G3, 0x92},
        };
 
        /*
@@ -356,7 +406,17 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
                core_clk_rate = DEFAULT_CLK_RATE_HZ;
 
        core_clk_cycles_per_us = core_clk_rate / USEC_PER_SEC;
-       ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US);
+       if (ufshcd_readl(hba, REG_UFS_SYS1CLK_1US) != core_clk_cycles_per_us) {
+               ufshcd_writel(hba, core_clk_cycles_per_us, REG_UFS_SYS1CLK_1US);
+               /*
+                * make sure above write gets applied before we return from
+                * this function.
+                */
+               mb();
+       }
+
+       if (ufs_qcom_cap_qunipro(host))
+               goto out;
 
        core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate;
        core_clk_period_in_ns <<= OFFSET_CLK_NS_REG;
@@ -406,35 +466,59 @@ ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
                goto out_error;
        }
 
-       /* this register 2 fields shall be written at once */
-       ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us,
-                                               REG_UFS_TX_SYMBOL_CLK_NS_US);
+       if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) !=
+           (core_clk_period_in_ns | tx_clk_cycles_per_us)) {
+               /* this register 2 fields shall be written at once */
+               ufshcd_writel(hba, core_clk_period_in_ns | tx_clk_cycles_per_us,
+                             REG_UFS_TX_SYMBOL_CLK_NS_US);
+               /*
+                * make sure above write gets applied before we return from
+                * this function.
+                */
+               mb();
+       }
+
+       if (update_link_startup_timer) {
+               ufshcd_writel(hba, ((core_clk_rate / MSEC_PER_SEC) * 100),
+                             REG_UFS_PA_LINK_STARTUP_TIMER);
+               /*
+                * make sure that this configuration is applied before
+                * we return
+                */
+               mb();
+       }
        goto out;
 
 out_error:
-       core_clk_rate = 0;
+       ret = -EINVAL;
 out:
-       return core_clk_rate;
+       return ret;
 }
 
-static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status)
+static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
+                                       enum ufs_notify_change_status status)
 {
-       unsigned long core_clk_rate = 0;
-       u32 core_clk_cycles_per_100ms;
+       int err = 0;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
        switch (status) {
        case PRE_CHANGE:
-               core_clk_rate = ufs_qcom_cfg_timers(hba, UFS_PWM_G1,
-                                                   SLOWAUTO_MODE, 0);
-               if (!core_clk_rate) {
+               if (ufs_qcom_cfg_timers(hba, UFS_PWM_G1, SLOWAUTO_MODE,
+                                       0, true)) {
                        dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
                                __func__);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out;
                }
-               core_clk_cycles_per_100ms =
-                       (core_clk_rate / MSEC_PER_SEC) * 100;
-               ufshcd_writel(hba, core_clk_cycles_per_100ms,
-                                       REG_UFS_PA_LINK_STARTUP_TIMER);
+
+               if (ufs_qcom_cap_qunipro(host))
+                       /*
+                        * set unipro core clock cycles to 150 & clear clock
+                        * divider
+                        */
+                       err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
+                                                                         150);
+
                break;
        case POST_CHANGE:
                ufs_qcom_link_startup_post_change(hba);
@@ -443,12 +527,13 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, bool status)
                break;
        }
 
-       return 0;
+out:
+       return err;
 }
 
 static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct phy *phy = host->generic_phy;
        int ret = 0;
 
@@ -470,8 +555,10 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
         * If UniPro link is not active, PHY ref_clk, main PHY analog power
         * rail and low noise analog power rail for PLL can be switched off.
         */
-       if (!ufs_qcom_is_link_active(hba))
+       if (!ufs_qcom_is_link_active(hba)) {
+               ufs_qcom_disable_lane_clks(host);
                phy_power_off(phy);
+       }
 
 out:
        return ret;
@@ -479,7 +566,7 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 
 static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct phy *phy = host->generic_phy;
        int err;
 
@@ -490,6 +577,10 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                goto out;
        }
 
+       err = ufs_qcom_enable_lane_clks(host);
+       if (err)
+               goto out;
+
        hba->is_sys_suspended = false;
 
 out:
@@ -594,6 +685,81 @@ static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param,
        return 0;
 }
 
+#ifdef CONFIG_MSM_BUS_SCALING
+static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
+               const char *speed_mode)
+{
+       struct device *dev = host->hba->dev;
+       struct device_node *np = dev->of_node;
+       int err;
+       const char *key = "qcom,bus-vector-names";
+
+       if (!speed_mode) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN"))
+               err = of_property_match_string(np, key, "MAX");
+       else
+               err = of_property_match_string(np, key, speed_mode);
+
+out:
+       if (err < 0)
+               dev_err(dev, "%s: Invalid %s mode %d\n",
+                               __func__, speed_mode, err);
+       return err;
+}
+
+static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
+{
+       int gear = max_t(u32, p->gear_rx, p->gear_tx);
+       int lanes = max_t(u32, p->lane_rx, p->lane_tx);
+       int pwr;
+
+       /* default to PWM Gear 1, Lane 1 if power mode is not initialized */
+       if (!gear)
+               gear = 1;
+
+       if (!lanes)
+               lanes = 1;
+
+       if (!p->pwr_rx && !p->pwr_tx) {
+               pwr = SLOWAUTO_MODE;
+               snprintf(result, BUS_VECTOR_NAME_LEN, "MIN");
+       } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
+                p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
+               pwr = FAST_MODE;
+               snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
+                        p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
+       } else {
+               pwr = SLOW_MODE;
+               snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
+                        "PWM", gear, lanes);
+       }
+}
+
+static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
+{
+       int err = 0;
+
+       if (vote != host->bus_vote.curr_vote) {
+               err = msm_bus_scale_client_update_request(
+                               host->bus_vote.client_handle, vote);
+               if (err) {
+                       dev_err(host->hba->dev,
+                               "%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n",
+                               __func__, host->bus_vote.client_handle,
+                               vote, err);
+                       goto out;
+               }
+
+               host->bus_vote.curr_vote = vote;
+       }
+out:
+       return err;
+}
+
 static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
 {
        int vote;
@@ -615,13 +781,137 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
        return err;
 }
 
+static ssize_t
+show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       host->bus_vote.is_max_bw_needed);
+}
+
+static ssize_t
+store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+       uint32_t value;
+
+       if (!kstrtou32(buf, 0, &value)) {
+               host->bus_vote.is_max_bw_needed = !!value;
+               ufs_qcom_update_bus_bw_vote(host);
+       }
+
+       return count;
+}
+
+static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
+{
+       int err;
+       struct msm_bus_scale_pdata *bus_pdata;
+       struct device *dev = host->hba->dev;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct device_node *np = dev->of_node;
+
+       bus_pdata = msm_bus_cl_get_pdata(pdev);
+       if (!bus_pdata) {
+               dev_err(dev, "%s: failed to get bus vectors\n", __func__);
+               err = -ENODATA;
+               goto out;
+       }
+
+       err = of_property_count_strings(np, "qcom,bus-vector-names");
+       if (err < 0 || err != bus_pdata->num_usecases) {
+               dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n",
+                               __func__, err);
+               goto out;
+       }
+
+       host->bus_vote.client_handle = msm_bus_scale_register_client(bus_pdata);
+       if (!host->bus_vote.client_handle) {
+               dev_err(dev, "%s: msm_bus_scale_register_client failed\n",
+                               __func__);
+               err = -EFAULT;
+               goto out;
+       }
+
+       /* cache the vote index for minimum and maximum bandwidth */
+       host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN");
+       host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX");
+
+       host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw;
+       host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw;
+       sysfs_attr_init(&host->bus_vote.max_bus_bw.attr);
+       host->bus_vote.max_bus_bw.attr.name = "max_bus_bw";
+       host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
+       err = device_create_file(dev, &host->bus_vote.max_bus_bw);
+out:
+       return err;
+}
+#else /* CONFIG_MSM_BUS_SCALING */
+static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
+{
+       return 0;
+}
+
+static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
+{
+       return 0;
+}
+
+static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
+{
+       return 0;
+}
+#endif /* CONFIG_MSM_BUS_SCALING */
+
+static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
+{
+       if (host->dev_ref_clk_ctrl_mmio &&
+           (enable ^ host->is_dev_ref_clk_enabled)) {
+               u32 temp = readl_relaxed(host->dev_ref_clk_ctrl_mmio);
+
+               if (enable)
+                       temp |= host->dev_ref_clk_en_mask;
+               else
+                       temp &= ~host->dev_ref_clk_en_mask;
+
+               /*
+                * If we are here to disable this clock it might be immediately
+                * after entering into hibern8 in which case we need to make
+                * sure that device ref_clk is active at least 1us after the
+                * hibern8 enter.
+                */
+               if (!enable)
+                       udelay(1);
+
+               writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio);
+
+               /* ensure that ref_clk is enabled/disabled before we return */
+               wmb();
+
+               /*
+                * If we call hibern8 exit after this, we need to make sure that
+                * device ref_clk is stable for at least 1us before the hibern8
+                * exit command.
+                */
+               if (enable)
+                       udelay(1);
+
+               host->is_dev_ref_clk_enabled = enable;
+       }
+}
+
 static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
-                               bool status,
+                               enum ufs_notify_change_status status,
                                struct ufs_pa_layer_attr *dev_max_params,
                                struct ufs_pa_layer_attr *dev_req_params)
 {
        u32 val;
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct phy *phy = host->generic_phy;
        struct ufs_qcom_dev_params ufs_qcom_cap;
        int ret = 0;
@@ -649,6 +939,20 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
                ufs_qcom_cap.desired_working_mode =
                                        UFS_QCOM_LIMIT_DESIRED_MODE;
 
+               if (host->hw_ver.major == 0x1) {
+                       /*
+                        * HS-G3 operations may not reliably work on legacy QCOM
+                        * UFS host controller hardware even though capability
+                        * exchange during link startup phase may end up
+                        * negotiating maximum supported gear as G3.
+                        * Hence downgrade the maximum supported gear to HS-G2.
+                        */
+                       if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G2)
+                               ufs_qcom_cap.hs_tx_gear = UFS_HS_G2;
+                       if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2)
+                               ufs_qcom_cap.hs_rx_gear = UFS_HS_G2;
+               }
+
                ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap,
                                                 dev_max_params,
                                                 dev_req_params);
@@ -660,9 +964,9 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
 
                break;
        case POST_CHANGE:
-               if (!ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
+               if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
                                        dev_req_params->pwr_rx,
-                                       dev_req_params->hs_rate)) {
+                                       dev_req_params->hs_rate, false)) {
                        dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
                                __func__);
                        /*
@@ -696,7 +1000,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
 
 static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
        if (host->hw_ver.major == 0x1)
                return UFSHCI_VERSION_11;
@@ -715,7 +1019,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
  */
 static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
        if (host->hw_ver.major == 0x01) {
                hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
@@ -724,10 +1028,11 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
 
                if (host->hw_ver.minor == 0x0001 && host->hw_ver.step == 0x0001)
                        hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR;
+
+               hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
        }
 
        if (host->hw_ver.major >= 0x2) {
-               hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
                hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
 
                if (!ufs_qcom_cap_qunipro(host))
@@ -740,79 +1045,29 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
 
 static void ufs_qcom_set_caps(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
-       if (host->hw_ver.major >= 0x2)
-               host->caps = UFS_QCOM_CAP_QUNIPRO;
-}
-
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
-               const char *speed_mode)
-{
-       struct device *dev = host->hba->dev;
-       struct device_node *np = dev->of_node;
-       int err;
-       const char *key = "qcom,bus-vector-names";
-
-       if (!speed_mode) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN"))
-               err = of_property_match_string(np, key, "MAX");
-       else
-               err = of_property_match_string(np, key, speed_mode);
-
-out:
-       if (err < 0)
-               dev_err(dev, "%s: Invalid %s mode %d\n",
-                               __func__, speed_mode, err);
-       return err;
-}
-
-static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
-{
-       int err = 0;
-
-       if (vote != host->bus_vote.curr_vote)
-               host->bus_vote.curr_vote = vote;
-
-       return err;
-}
-
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
-{
-       int gear = max_t(u32, p->gear_rx, p->gear_tx);
-       int lanes = max_t(u32, p->lane_rx, p->lane_tx);
-       int pwr;
-
-       /* default to PWM Gear 1, Lane 1 if power mode is not initialized */
-       if (!gear)
-               gear = 1;
-
-       if (!lanes)
-               lanes = 1;
+       hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
+       hba->caps |= UFSHCD_CAP_CLK_SCALING;
+       hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
 
-       if (!p->pwr_rx && !p->pwr_tx) {
-               pwr = SLOWAUTO_MODE;
-               snprintf(result, BUS_VECTOR_NAME_LEN, "MIN");
-       } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
-                p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
-               pwr = FAST_MODE;
-               snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
-                        p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
-       } else {
-               pwr = SLOW_MODE;
-               snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
-                        "PWM", gear, lanes);
+       if (host->hw_ver.major >= 0x2) {
+               host->caps = UFS_QCOM_CAP_QUNIPRO |
+                            UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE;
        }
 }
 
+/**
+ * ufs_qcom_setup_clocks - enables/disable clocks
+ * @hba: host controller instance
+ * @on: If true, enable clocks else disable them.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
 static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
 {
-       struct ufs_qcom_host *host = hba->priv;
-       int err = 0;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+       int err;
        int vote = 0;
 
        /*
@@ -835,20 +1090,18 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
                        ufs_qcom_phy_disable_iface_clk(host->generic_phy);
                        goto out;
                }
-               /* enable the device ref clock */
-               ufs_qcom_phy_enable_dev_ref_clk(host->generic_phy);
                vote = host->bus_vote.saved_vote;
                if (vote == host->bus_vote.min_bw_vote)
                        ufs_qcom_update_bus_bw_vote(host);
+
        } else {
+
                /* M-PHY RMMI interface clocks can be turned off */
                ufs_qcom_phy_disable_iface_clk(host->generic_phy);
-               if (!ufs_qcom_is_link_active(hba)) {
-                       /* turn off UFS local PHY ref_clk */
-                       ufs_qcom_phy_disable_ref_clk(host->generic_phy);
+               if (!ufs_qcom_is_link_active(hba))
                        /* disable device ref_clk */
-                       ufs_qcom_phy_disable_dev_ref_clk(host->generic_phy);
-               }
+                       ufs_qcom_dev_ref_clk_ctrl(host, false);
+
                vote = host->bus_vote.min_bw_vote;
        }
 
@@ -861,68 +1114,17 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
        return err;
 }
 
-static ssize_t
-show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
-                       char *buf)
-{
-       struct ufs_hba *hba = dev_get_drvdata(dev);
-       struct ufs_qcom_host *host = hba->priv;
-
-       return snprintf(buf, PAGE_SIZE, "%u\n",
-                       host->bus_vote.is_max_bw_needed);
-}
-
-static ssize_t
-store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct ufs_hba *hba = dev_get_drvdata(dev);
-       struct ufs_qcom_host *host = hba->priv;
-       uint32_t value;
-
-       if (!kstrtou32(buf, 0, &value)) {
-               host->bus_vote.is_max_bw_needed = !!value;
-               ufs_qcom_update_bus_bw_vote(host);
-       }
-
-       return count;
-}
-
-static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
-{
-       int err;
-       struct device *dev = host->hba->dev;
-       struct device_node *np = dev->of_node;
-
-       err = of_property_count_strings(np, "qcom,bus-vector-names");
-       if (err < 0 ) {
-               dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n",
-                               __func__, err);
-               goto out;
-       }
-
-       /* cache the vote index for minimum and maximum bandwidth */
-       host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN");
-       host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX");
-
-       host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw;
-       host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw;
-       sysfs_attr_init(&host->bus_vote.max_bus_bw.attr);
-       host->bus_vote.max_bus_bw.attr.name = "max_bus_bw";
-       host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
-       err = device_create_file(dev, &host->bus_vote.max_bus_bw);
-out:
-       return err;
-}
-
 #define        ANDROID_BOOT_DEV_MAX    30
 static char android_boot_dev[ANDROID_BOOT_DEV_MAX];
-static int get_android_boot_dev(char *str)
+
+#ifndef MODULE
+static int __init get_android_boot_dev(char *str)
 {
        strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX);
        return 1;
 }
 __setup("androidboot.bootdevice=", get_android_boot_dev);
+#endif
 
 /**
  * ufs_qcom_init - bind phy with controller
@@ -938,7 +1140,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
 {
        int err;
        struct device *dev = hba->dev;
+       struct platform_device *pdev = to_platform_device(dev);
        struct ufs_qcom_host *host;
+       struct resource *res;
 
        if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev)))
                return -ENODEV;
@@ -950,9 +1154,15 @@ static int ufs_qcom_init(struct ufs_hba *hba)
                goto out;
        }
 
+       /* Make a two way bind between the qcom host and the hba */
        host->hba = hba;
-       hba->priv = (void *)host;
+       ufshcd_set_variant(hba, host);
 
+       /*
+        * voting/devoting device ref_clk source is time consuming hence
+        * skip devoting it during aggressive clock gating. This clock
+        * will still be gated off during runtime suspend.
+        */
        host->generic_phy = devm_phy_get(dev, "ufsphy");
 
        if (IS_ERR(host->generic_phy)) {
@@ -968,6 +1178,30 @@ static int ufs_qcom_init(struct ufs_hba *hba)
        ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
                &host->hw_ver.minor, &host->hw_ver.step);
 
+       /*
+        * for newer controllers, device reference clock control bit has
+        * moved inside UFS controller register address space itself.
+        */
+       if (host->hw_ver.major >= 0x02) {
+               host->dev_ref_clk_ctrl_mmio = hba->mmio_base + REG_UFS_CFG1;
+               host->dev_ref_clk_en_mask = BIT(26);
+       } else {
+               /* "dev_ref_clk_ctrl_mem" is optional resource */
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               if (res) {
+                       host->dev_ref_clk_ctrl_mmio =
+                                       devm_ioremap_resource(dev, res);
+                       if (IS_ERR(host->dev_ref_clk_ctrl_mmio)) {
+                               dev_warn(dev,
+                                       "%s: could not map dev_ref_clk_ctrl_mmio, err %ld\n",
+                                       __func__,
+                                       PTR_ERR(host->dev_ref_clk_ctrl_mmio));
+                               host->dev_ref_clk_ctrl_mmio = NULL;
+                       }
+                       host->dev_ref_clk_en_mask = BIT(5);
+               }
+       }
+
        /* update phy revision information before calling phy_init() */
        ufs_qcom_phy_save_controller_version(host->generic_phy,
                host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step);
@@ -984,14 +1218,20 @@ static int ufs_qcom_init(struct ufs_hba *hba)
        ufs_qcom_set_caps(hba);
        ufs_qcom_advertise_quirks(hba);
 
-       hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING;
-       hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
-
        ufs_qcom_setup_clocks(hba, true);
 
        if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
                ufs_qcom_hosts[hba->dev->id] = host;
 
+       host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN;
+       ufs_qcom_get_default_testbus_cfg(host);
+       err = ufs_qcom_testbus_config(host);
+       if (err) {
+               dev_warn(dev, "%s: failed to configure the testbus %d\n",
+                               __func__, err);
+               err = 0;
+       }
+
        goto out;
 
 out_disable_phy:
@@ -1000,40 +1240,266 @@ static int ufs_qcom_init(struct ufs_hba *hba)
        phy_exit(host->generic_phy);
 out_host_free:
        devm_kfree(dev, host);
-       hba->priv = NULL;
+       ufshcd_set_variant(hba, NULL);
 out:
        return err;
 }
 
 static void ufs_qcom_exit(struct ufs_hba *hba)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
        ufs_qcom_disable_lane_clks(host);
        phy_power_off(host->generic_phy);
 }
 
-static
-void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
+static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
+                                                      u32 clk_cycles)
+{
+       int err;
+       u32 core_clk_ctrl_reg;
+
+       if (clk_cycles > DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK)
+               return -EINVAL;
+
+       err = ufshcd_dme_get(hba,
+                           UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+                           &core_clk_ctrl_reg);
+       if (err)
+               goto out;
+
+       core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK;
+       core_clk_ctrl_reg |= clk_cycles;
+
+       /* Clear CORE_CLK_DIV_EN */
+       core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
+
+       err = ufshcd_dme_set(hba,
+                           UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+                           core_clk_ctrl_reg);
+out:
+       return err;
+}
+
+static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)
+{
+       /* nothing to do as of now */
+       return 0;
+}
+
+static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba)
+{
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+       if (!ufs_qcom_cap_qunipro(host))
+               return 0;
+
+       /* set unipro core clock cycles to 150 and clear clock divider */
+       return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150);
+}
+
+static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
+{
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+       int err;
+       u32 core_clk_ctrl_reg;
+
+       if (!ufs_qcom_cap_qunipro(host))
+               return 0;
+
+       err = ufshcd_dme_get(hba,
+                           UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+                           &core_clk_ctrl_reg);
+
+       /* make sure CORE_CLK_DIV_EN is cleared */
+       if (!err &&
+           (core_clk_ctrl_reg & DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT)) {
+               core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
+               err = ufshcd_dme_set(hba,
+                                   UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
+                                   core_clk_ctrl_reg);
+       }
+
+       return err;
+}
+
+static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba)
+{
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+       if (!ufs_qcom_cap_qunipro(host))
+               return 0;
+
+       /* set unipro core clock cycles to 75 and clear clock divider */
+       return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 75);
+}
+
+static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
+               bool scale_up, enum ufs_notify_change_status status)
 {
-       struct ufs_qcom_host *host = hba->priv;
+       struct ufs_qcom_host *host = ufshcd_get_variant(hba);
        struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params;
+       int err = 0;
 
-       if (!dev_req_params)
-               return;
+       if (status == PRE_CHANGE) {
+               if (scale_up)
+                       err = ufs_qcom_clk_scale_up_pre_change(hba);
+               else
+                       err = ufs_qcom_clk_scale_down_pre_change(hba);
+       } else {
+               if (scale_up)
+                       err = ufs_qcom_clk_scale_up_post_change(hba);
+               else
+                       err = ufs_qcom_clk_scale_down_post_change(hba);
 
-       ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
-                               dev_req_params->pwr_rx,
-                               dev_req_params->hs_rate);
+               if (err || !dev_req_params)
+                       goto out;
+
+               ufs_qcom_cfg_timers(hba,
+                                   dev_req_params->gear_rx,
+                                   dev_req_params->pwr_rx,
+                                   dev_req_params->hs_rate,
+                                   false);
+               ufs_qcom_update_bus_bw_vote(host);
+       }
+
+out:
+       return err;
 }
 
+static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
+{
+       /* provide a legal default configuration */
+       host->testbus.select_major = TSTBUS_UAWM;
+       host->testbus.select_minor = 1;
+}
+
+static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host)
+{
+       if (host->testbus.select_major >= TSTBUS_MAX) {
+               dev_err(host->hba->dev,
+                       "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n",
+                       __func__, host->testbus.select_major);
+               return false;
+       }
+
+       /*
+        * Not performing check for each individual select_major
+        * mappings of select_minor, since there is no harm in
+        * configuring a non-existent select_minor
+        */
+       if (host->testbus.select_minor > 0x1F) {
+               dev_err(host->hba->dev,
+                       "%s: 0x%05X is not a legal testbus option\n",
+                       __func__, host->testbus.select_minor);
+               return false;
+       }
+
+       return true;
+}
+
+int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
+{
+       int reg;
+       int offset;
+       u32 mask = TEST_BUS_SUB_SEL_MASK;
+
+       if (!host)
+               return -EINVAL;
+
+       if (!ufs_qcom_testbus_cfg_is_ok(host))
+               return -EPERM;
+
+       switch (host->testbus.select_major) {
+       case TSTBUS_UAWM:
+               reg = UFS_TEST_BUS_CTRL_0;
+               offset = 24;
+               break;
+       case TSTBUS_UARM:
+               reg = UFS_TEST_BUS_CTRL_0;
+               offset = 16;
+               break;
+       case TSTBUS_TXUC:
+               reg = UFS_TEST_BUS_CTRL_0;
+               offset = 8;
+               break;
+       case TSTBUS_RXUC:
+               reg = UFS_TEST_BUS_CTRL_0;
+               offset = 0;
+               break;
+       case TSTBUS_DFC:
+               reg = UFS_TEST_BUS_CTRL_1;
+               offset = 24;
+               break;
+       case TSTBUS_TRLUT:
+               reg = UFS_TEST_BUS_CTRL_1;
+               offset = 16;
+               break;
+       case TSTBUS_TMRLUT:
+               reg = UFS_TEST_BUS_CTRL_1;
+               offset = 8;
+               break;
+       case TSTBUS_OCSC:
+               reg = UFS_TEST_BUS_CTRL_1;
+               offset = 0;
+               break;
+       case TSTBUS_WRAPPER:
+               reg = UFS_TEST_BUS_CTRL_2;
+               offset = 16;
+               break;
+       case TSTBUS_COMBINED:
+               reg = UFS_TEST_BUS_CTRL_2;
+               offset = 8;
+               break;
+       case TSTBUS_UTP_HCI:
+               reg = UFS_TEST_BUS_CTRL_2;
+               offset = 0;
+               break;
+       case TSTBUS_UNIPRO:
+               reg = UFS_UNIPRO_CFG;
+               offset = 1;
+               break;
+       /*
+        * No need for a default case, since
+        * ufs_qcom_testbus_cfg_is_ok() checks that the configuration
+        * is legal
+        */
+       }
+       mask <<= offset;
+
+       pm_runtime_get_sync(host->hba->dev);
+       ufshcd_hold(host->hba, false);
+       ufshcd_rmwl(host->hba, TEST_BUS_SEL,
+                   (u32)host->testbus.select_major << 19,
+                   REG_UFS_CFG1);
+       ufshcd_rmwl(host->hba, mask,
+                   (u32)host->testbus.select_minor << offset,
+                   reg);
+       ufshcd_release(host->hba);
+       pm_runtime_put_sync(host->hba->dev);
+
+       return 0;
+}
+
+static void ufs_qcom_testbus_read(struct ufs_hba *hba)
+{
+       ufs_qcom_dump_regs(hba, UFS_TEST_BUS, 1, "UFS_TEST_BUS ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+       ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
+                       "HCI Vendor Specific Registers ");
+
+       ufs_qcom_testbus_read(hba);
+}
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
  * The variant operations configure the necessary controller and PHY
  * handshake during initialization.
  */
-static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
+static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
        .name                   = "qcom",
        .init                   = ufs_qcom_init,
        .exit                   = ufs_qcom_exit,
@@ -1045,5 +1511,66 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
        .pwr_change_notify      = ufs_qcom_pwr_change_notify,
        .suspend                = ufs_qcom_suspend,
        .resume                 = ufs_qcom_resume,
+       .dbg_register_dump      = ufs_qcom_dump_dbg_regs,
+};
+
+/**
+ * ufs_qcom_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Return zero for success and non-zero for failure
+ */
+static int ufs_qcom_probe(struct platform_device *pdev)
+{
+       int err;
+       struct device *dev = &pdev->dev;
+
+       /* Perform generic probe */
+       err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops);
+       if (err)
+               dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
+
+       return err;
+}
+
+/**
+ * ufs_qcom_remove - set driver_data of the device to NULL
+ * @pdev: pointer to platform device handle
+ *
+ * Always return 0
+ */
+static int ufs_qcom_remove(struct platform_device *pdev)
+{
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+       pm_runtime_get_sync(&(pdev)->dev);
+       ufshcd_remove(hba);
+       return 0;
+}
+
+static const struct of_device_id ufs_qcom_of_match[] = {
+       { .compatible = "qcom,ufshc"},
+       {},
+};
+
+static const struct dev_pm_ops ufs_qcom_pm_ops = {
+       .suspend        = ufshcd_pltfrm_suspend,
+       .resume         = ufshcd_pltfrm_resume,
+       .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
+       .runtime_resume  = ufshcd_pltfrm_runtime_resume,
+       .runtime_idle    = ufshcd_pltfrm_runtime_idle,
 };
-EXPORT_SYMBOL(ufs_hba_qcom_vops);
+
+static struct platform_driver ufs_qcom_pltform = {
+       .probe  = ufs_qcom_probe,
+       .remove = ufs_qcom_remove,
+       .shutdown = ufshcd_pltfrm_shutdown,
+       .driver = {
+               .name   = "ufshcd-qcom",
+               .pm     = &ufs_qcom_pm_ops,
+               .of_match_table = of_match_ptr(ufs_qcom_of_match),
+       },
+};
+module_platform_driver(ufs_qcom_pltform);
+
+MODULE_LICENSE("GPL v2");
index db2c0a00e846282b37688e850a994e584ecb46d7..36249b35f8584939c74501068e0a730192dff94a 100644 (file)
@@ -35,8 +35,8 @@
 
 #define UFS_QCOM_LIMIT_NUM_LANES_RX    2
 #define UFS_QCOM_LIMIT_NUM_LANES_TX    2
-#define UFS_QCOM_LIMIT_HSGEAR_RX       UFS_HS_G2
-#define UFS_QCOM_LIMIT_HSGEAR_TX       UFS_HS_G2
+#define UFS_QCOM_LIMIT_HSGEAR_RX       UFS_HS_G3
+#define UFS_QCOM_LIMIT_HSGEAR_TX       UFS_HS_G3
 #define UFS_QCOM_LIMIT_PWMGEAR_RX      UFS_PWM_G4
 #define UFS_QCOM_LIMIT_PWMGEAR_TX      UFS_PWM_G4
 #define UFS_QCOM_LIMIT_RX_PWR_PWM      SLOW_MODE
@@ -58,6 +58,21 @@ enum {
        REG_UFS_CFG2                        = 0xE0,
        REG_UFS_HW_VERSION                  = 0xE4,
 
+       UFS_TEST_BUS                            = 0xE8,
+       UFS_TEST_BUS_CTRL_0                     = 0xEC,
+       UFS_TEST_BUS_CTRL_1                     = 0xF0,
+       UFS_TEST_BUS_CTRL_2                     = 0xF4,
+       UFS_UNIPRO_CFG                          = 0xF8,
+
+       /*
+        * QCOM UFS host controller vendor specific registers
+        * added in HW Version 3.0.0
+        */
+       UFS_AH8_CFG                             = 0xFC,
+};
+
+/* QCOM UFS host controller vendor specific debug registers */
+enum {
        UFS_DBG_RD_REG_UAWM                     = 0x100,
        UFS_DBG_RD_REG_UARM                     = 0x200,
        UFS_DBG_RD_REG_TXUC                     = 0x300,
@@ -73,6 +88,14 @@ enum {
        UFS_UFS_DBG_RD_EDTL_RAM                 = 0x1900,
 };
 
+#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x)     (0x000 + x)
+#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x)     (0x400 + x)
+
+/* bit definitions for REG_UFS_CFG1 register */
+#define QUNIPRO_SEL    UFS_BIT(0)
+#define TEST_BUS_EN            BIT(18)
+#define TEST_BUS_SEL           GENMASK(22, 19)
+
 /* bit definitions for REG_UFS_CFG2 register */
 #define UAWM_HW_CGC_EN         (1 << 0)
 #define UARM_HW_CGC_EN         (1 << 1)
@@ -83,6 +106,9 @@ enum {
 #define TMRLUT_HW_CGC_EN       (1 << 6)
 #define OCSC_HW_CGC_EN         (1 << 7)
 
+/* bit definition for UFS_UFS_TEST_BUS_CTRL_n */
+#define TEST_BUS_SUB_SEL_MASK  0x1F  /* All XXX_SEL fields are 5 bits wide */
+
 #define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\
                                 TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\
                                 DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\
@@ -106,6 +132,21 @@ enum ufs_qcom_phy_init_type {
        UFS_PHY_INIT_CFG_RESTORE,
 };
 
+/* QCOM UFS debug print bit mask */
+#define UFS_QCOM_DBG_PRINT_REGS_EN     BIT(0)
+#define UFS_QCOM_DBG_PRINT_ICE_REGS_EN BIT(1)
+#define UFS_QCOM_DBG_PRINT_TEST_BUS_EN BIT(2)
+
+#define UFS_QCOM_DBG_PRINT_ALL \
+       (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_ICE_REGS_EN | \
+        UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+
+/* QUniPro Vendor specific attributes */
+#define DME_VS_CORE_CLK_CTRL   0xD002
+/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
+#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT               BIT(8)
+#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK      0xFF
+
 static inline void
 ufs_qcom_get_controller_revision(struct ufs_hba *hba,
                                 u8 *major, u16 *minor, u16 *step)
@@ -157,8 +198,13 @@ struct ufs_hw_version {
        u16 minor;
        u8 major;
 };
-struct ufs_qcom_host {
 
+struct ufs_qcom_testbus {
+       u8 select_major;
+       u8 select_minor;
+};
+
+struct ufs_qcom_host {
        /*
         * Set this capability if host controller supports the QUniPro mode
         * and if driver wants the Host controller to operate in QUniPro mode.
@@ -166,6 +212,12 @@ struct ufs_qcom_host {
         * controller supports the QUniPro mode.
         */
        #define UFS_QCOM_CAP_QUNIPRO    UFS_BIT(0)
+
+       /*
+        * Set this capability if host controller can retain the secure
+        * configuration even after UFS controller core power collapse.
+        */
+       #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE  UFS_BIT(1)
        u32 caps;
 
        struct phy *generic_phy;
@@ -178,13 +230,23 @@ struct ufs_qcom_host {
        struct clk *tx_l1_sync_clk;
        bool is_lane_clks_enabled;
 
+       void __iomem *dev_ref_clk_ctrl_mmio;
+       bool is_dev_ref_clk_enabled;
        struct ufs_hw_version hw_ver;
+
+       u32 dev_ref_clk_en_mask;
+
+       /* Bitmask for enabling debug prints */
+       u32 dbg_print_en;
+       struct ufs_qcom_testbus testbus;
 };
 
 #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba)
 #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba)
 #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba)
 
+int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
+
 static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
 {
        if (host->caps & UFS_QCOM_CAP_QUNIPRO)
index 7db9564f507df27d7ddcfce6369a05e6622f7e41..9714f2a8b32977d7394838c888bda8b64c1210ef 100644 (file)
 #include <linux/of.h>
 
 #include "ufshcd.h"
-
-static const struct of_device_id ufs_of_match[];
-static struct ufs_hba_variant_ops *get_variant_ops(struct device *dev)
-{
-       if (dev->of_node) {
-               const struct of_device_id *match;
-
-               match = of_match_node(ufs_of_match, dev->of_node);
-               if (match)
-                       return (struct ufs_hba_variant_ops *)match->data;
-       }
-
-       return NULL;
-}
+#include "ufshcd-pltfrm.h"
 
 static int ufshcd_parse_clock_info(struct ufs_hba *hba)
 {
@@ -245,10 +232,11 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba)
  * Returns 0 if successful
  * Returns non-zero otherwise
  */
-static int ufshcd_pltfrm_suspend(struct device *dev)
+int ufshcd_pltfrm_suspend(struct device *dev)
 {
        return ufshcd_system_suspend(dev_get_drvdata(dev));
 }
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_suspend);
 
 /**
  * ufshcd_pltfrm_resume - resume power management function
@@ -257,43 +245,47 @@ static int ufshcd_pltfrm_suspend(struct device *dev)
  * Returns 0 if successful
  * Returns non-zero otherwise
  */
-static int ufshcd_pltfrm_resume(struct device *dev)
+int ufshcd_pltfrm_resume(struct device *dev)
 {
        return ufshcd_system_resume(dev_get_drvdata(dev));
 }
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_resume);
 
-static int ufshcd_pltfrm_runtime_suspend(struct device *dev)
+int ufshcd_pltfrm_runtime_suspend(struct device *dev)
 {
        return ufshcd_runtime_suspend(dev_get_drvdata(dev));
 }
-static int ufshcd_pltfrm_runtime_resume(struct device *dev)
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_suspend);
+
+int ufshcd_pltfrm_runtime_resume(struct device *dev)
 {
        return ufshcd_runtime_resume(dev_get_drvdata(dev));
 }
-static int ufshcd_pltfrm_runtime_idle(struct device *dev)
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_resume);
+
+int ufshcd_pltfrm_runtime_idle(struct device *dev)
 {
        return ufshcd_runtime_idle(dev_get_drvdata(dev));
 }
-#else /* !CONFIG_PM */
-#define ufshcd_pltfrm_suspend  NULL
-#define ufshcd_pltfrm_resume   NULL
-#define ufshcd_pltfrm_runtime_suspend  NULL
-#define ufshcd_pltfrm_runtime_resume   NULL
-#define ufshcd_pltfrm_runtime_idle     NULL
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle);
+
 #endif /* CONFIG_PM */
 
-static void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
+void ufshcd_pltfrm_shutdown(struct platform_device *pdev)
 {
        ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev));
 }
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown);
 
 /**
- * ufshcd_pltfrm_probe - probe routine of the driver
+ * ufshcd_pltfrm_init - probe routine of the driver
  * @pdev: pointer to Platform device handle
+ * @vops: pointer to variant ops
  *
  * Returns 0 on success, non-zero value on failure
  */
-static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+int ufshcd_pltfrm_init(struct platform_device *pdev,
+                      struct ufs_hba_variant_ops *vops)
 {
        struct ufs_hba *hba;
        void __iomem *mmio_base;
@@ -321,19 +313,19 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
                goto out;
        }
 
-       hba->vops = get_variant_ops(&pdev->dev);
+       hba->vops = vops;
 
        err = ufshcd_parse_clock_info(hba);
        if (err) {
                dev_err(&pdev->dev, "%s: clock parse failed %d\n",
                                __func__, err);
-               goto out;
+               goto dealloc_host;
        }
        err = ufshcd_parse_regulator_info(hba);
        if (err) {
                dev_err(&pdev->dev, "%s: regulator init failed %d\n",
                                __func__, err);
-               goto out;
+               goto dealloc_host;
        }
 
        pm_runtime_set_active(&pdev->dev);
@@ -352,50 +344,12 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
 out_disable_rpm:
        pm_runtime_disable(&pdev->dev);
        pm_runtime_set_suspended(&pdev->dev);
+dealloc_host:
+       ufshcd_dealloc_host(hba);
 out:
        return err;
 }
-
-/**
- * ufshcd_pltfrm_remove - remove platform driver routine
- * @pdev: pointer to platform device handle
- *
- * Returns 0 on success, non-zero value on failure
- */
-static int ufshcd_pltfrm_remove(struct platform_device *pdev)
-{
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
-       pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
-       return 0;
-}
-
-static const struct of_device_id ufs_of_match[] = {
-       { .compatible = "jedec,ufs-1.1"},
-       {},
-};
-
-static const struct dev_pm_ops ufshcd_dev_pm_ops = {
-       .suspend        = ufshcd_pltfrm_suspend,
-       .resume         = ufshcd_pltfrm_resume,
-       .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
-       .runtime_resume  = ufshcd_pltfrm_runtime_resume,
-       .runtime_idle    = ufshcd_pltfrm_runtime_idle,
-};
-
-static struct platform_driver ufshcd_pltfrm_driver = {
-       .probe  = ufshcd_pltfrm_probe,
-       .remove = ufshcd_pltfrm_remove,
-       .shutdown = ufshcd_pltfrm_shutdown,
-       .driver = {
-               .name   = "ufshcd",
-               .pm     = &ufshcd_dev_pm_ops,
-               .of_match_table = ufs_of_match,
-       },
-};
-
-module_platform_driver(ufshcd_pltfrm_driver);
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init);
 
 MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
 MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h
new file mode 100644 (file)
index 0000000..df64c41
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (c) 2015, The Linux Foundation. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 UFSHCD_PLTFRM_H_
+#define UFSHCD_PLTFRM_H_
+
+#include "ufshcd.h"
+
+int ufshcd_pltfrm_init(struct platform_device *pdev,
+                      struct ufs_hba_variant_ops *vops);
+void ufshcd_pltfrm_shutdown(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+
+int ufshcd_pltfrm_suspend(struct device *dev);
+int ufshcd_pltfrm_resume(struct device *dev);
+int ufshcd_pltfrm_runtime_suspend(struct device *dev);
+int ufshcd_pltfrm_runtime_resume(struct device *dev);
+int ufshcd_pltfrm_runtime_idle(struct device *dev);
+
+#else /* !CONFIG_PM */
+
+#define ufshcd_pltfrm_suspend  NULL
+#define ufshcd_pltfrm_resume   NULL
+#define ufshcd_pltfrm_runtime_suspend  NULL
+#define ufshcd_pltfrm_runtime_resume   NULL
+#define ufshcd_pltfrm_runtime_idle     NULL
+
+#endif /* CONFIG_PM */
+
+#endif /* UFSHCD_PLTFRM_H_ */
index b0ade73f8c6a66a6a5f4d32fcbc4ac266b43d7eb..85cd2564c15773f728e8bd6ae6fcde28867ab2bb 100644 (file)
@@ -271,10 +271,8 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
-       if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
-               if (hba->vops && hba->vops->get_ufs_hci_version)
-                       return hba->vops->get_ufs_hci_version(hba);
-       }
+       if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION)
+               return ufshcd_vops_get_ufs_hci_version(hba);
 
        return ufshcd_readl(hba, REG_UFS_VERSION);
 }
@@ -627,6 +625,7 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 out:
        return rc;
 }
+EXPORT_SYMBOL_GPL(ufshcd_hold);
 
 static void ufshcd_gate_work(struct work_struct *work)
 {
@@ -714,6 +713,7 @@ void ufshcd_release(struct ufs_hba *hba)
        __ufshcd_release(hba);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
 }
+EXPORT_SYMBOL_GPL(ufshcd_release);
 
 static ssize_t ufshcd_clkgate_delay_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -2473,9 +2473,8 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
                dev_err(hba->dev,
                        "%s: power mode change failed %d\n", __func__, ret);
        } else {
-               if (hba->vops && hba->vops->pwr_change_notify)
-                       hba->vops->pwr_change_notify(hba,
-                               POST_CHANGE, NULL, pwr_mode);
+               ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
+                                                               pwr_mode);
 
                memcpy(&hba->pwr_info, pwr_mode,
                        sizeof(struct ufs_pa_layer_attr));
@@ -2495,10 +2494,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
        struct ufs_pa_layer_attr final_params = { 0 };
        int ret;
 
-       if (hba->vops && hba->vops->pwr_change_notify)
-               hba->vops->pwr_change_notify(hba,
-                    PRE_CHANGE, desired_pwr_mode, &final_params);
-       else
+       ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE,
+                                       desired_pwr_mode, &final_params);
+
+       if (ret)
                memcpy(&final_params, desired_pwr_mode, sizeof(final_params));
 
        ret = ufshcd_change_power_mode(hba, &final_params);
@@ -2647,8 +2646,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
        /* UniPro link is disabled at this point */
        ufshcd_set_link_off(hba);
 
-       if (hba->vops && hba->vops->hce_enable_notify)
-               hba->vops->hce_enable_notify(hba, PRE_CHANGE);
+       ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
 
        /* start controller initialization sequence */
        ufshcd_hba_start(hba);
@@ -2681,8 +2679,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
        /* enable UIC related interrupts */
        ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
 
-       if (hba->vops && hba->vops->hce_enable_notify)
-               hba->vops->hce_enable_notify(hba, POST_CHANGE);
+       ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
 
        return 0;
 }
@@ -2735,8 +2732,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
        int retries = DME_LINKSTARTUP_RETRIES;
 
        do {
-               if (hba->vops && hba->vops->link_startup_notify)
-                       hba->vops->link_startup_notify(hba, PRE_CHANGE);
+               ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);
 
                ret = ufshcd_dme_link_startup(hba);
 
@@ -2767,11 +2763,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
        }
 
        /* Include any host controller configuration via UIC commands */
-       if (hba->vops && hba->vops->link_startup_notify) {
-               ret = hba->vops->link_startup_notify(hba, POST_CHANGE);
-               if (ret)
-                       goto out;
-       }
+       ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
+       if (ret)
+               goto out;
 
        ret = ufshcd_make_hba_operational(hba);
 out:
@@ -4355,7 +4349,6 @@ static struct scsi_host_template ufshcd_driver_template = {
        .cmd_per_lun            = UFSHCD_CMD_PER_LUN,
        .can_queue              = UFSHCD_CAN_QUEUE,
        .max_host_blocked       = 1,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -4578,8 +4571,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
                }
        }
 
-       if (hba->vops && hba->vops->setup_clocks)
-               ret = hba->vops->setup_clocks(hba, on);
+       ret = ufshcd_vops_setup_clocks(hba, on);
 out:
        if (ret) {
                list_for_each_entry(clki, head, list) {
@@ -4645,27 +4637,22 @@ static int ufshcd_variant_hba_init(struct ufs_hba *hba)
        if (!hba->vops)
                goto out;
 
-       if (hba->vops->init) {
-               err = hba->vops->init(hba);
-               if (err)
-                       goto out;
-       }
+       err = ufshcd_vops_init(hba);
+       if (err)
+               goto out;
 
-       if (hba->vops->setup_regulators) {
-               err = hba->vops->setup_regulators(hba, true);
-               if (err)
-                       goto out_exit;
-       }
+       err = ufshcd_vops_setup_regulators(hba, true);
+       if (err)
+               goto out_exit;
 
        goto out;
 
 out_exit:
-       if (hba->vops->exit)
-               hba->vops->exit(hba);
+       ufshcd_vops_exit(hba);
 out:
        if (err)
                dev_err(hba->dev, "%s: variant %s init failed err %d\n",
-                       __func__, hba->vops ? hba->vops->name : "", err);
+                       __func__, ufshcd_get_var_name(hba), err);
        return err;
 }
 
@@ -4674,14 +4661,11 @@ static void ufshcd_variant_hba_exit(struct ufs_hba *hba)
        if (!hba->vops)
                return;
 
-       if (hba->vops->setup_clocks)
-               hba->vops->setup_clocks(hba, false);
+       ufshcd_vops_setup_clocks(hba, false);
 
-       if (hba->vops->setup_regulators)
-               hba->vops->setup_regulators(hba, false);
+       ufshcd_vops_setup_regulators(hba, false);
 
-       if (hba->vops->exit)
-               hba->vops->exit(hba);
+       ufshcd_vops_exit(hba);
 }
 
 static int ufshcd_hba_init(struct ufs_hba *hba)
@@ -5058,17 +5042,13 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
         * vendor specific host controller register space call them before the
         * host clocks are ON.
         */
-       if (hba->vops && hba->vops->suspend) {
-               ret = hba->vops->suspend(hba, pm_op);
-               if (ret)
-                       goto set_link_active;
-       }
+       ret = ufshcd_vops_suspend(hba, pm_op);
+       if (ret)
+               goto set_link_active;
 
-       if (hba->vops && hba->vops->setup_clocks) {
-               ret = hba->vops->setup_clocks(hba, false);
-               if (ret)
-                       goto vops_resume;
-       }
+       ret = ufshcd_vops_setup_clocks(hba, false);
+       if (ret)
+               goto vops_resume;
 
        if (!ufshcd_is_link_active(hba))
                ufshcd_setup_clocks(hba, false);
@@ -5079,7 +5059,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
        hba->clk_gating.state = CLKS_OFF;
        /*
         * Disable the host irq as host controller as there won't be any
-        * host controller trasanction expected till resume.
+        * host controller transaction expected till resume.
         */
        ufshcd_disable_irq(hba);
        /* Put the host controller in low power mode if possible */
@@ -5087,8 +5067,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
        goto out;
 
 vops_resume:
-       if (hba->vops && hba->vops->resume)
-               hba->vops->resume(hba, pm_op);
+       ufshcd_vops_resume(hba, pm_op);
 set_link_active:
        ufshcd_vreg_set_hpm(hba);
        if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
@@ -5144,11 +5123,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
         * vendor specific host controller register space call them when the
         * host clocks are ON.
         */
-       if (hba->vops && hba->vops->resume) {
-               ret = hba->vops->resume(hba, pm_op);
-               if (ret)
-                       goto disable_vreg;
-       }
+       ret = ufshcd_vops_resume(hba, pm_op);
+       if (ret)
+               goto disable_vreg;
 
        if (ufshcd_is_link_hibern8(hba)) {
                ret = ufshcd_uic_hibern8_exit(hba);
@@ -5189,8 +5166,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 set_old_link_state:
        ufshcd_link_state_transition(hba, old_link_state, 0);
 vendor_suspend:
-       if (hba->vops && hba->vops->suspend)
-               hba->vops->suspend(hba, pm_op);
+       ufshcd_vops_suspend(hba, pm_op);
 disable_vreg:
        ufshcd_vreg_set_lpm(hba);
 disable_irq_and_vops_clks:
@@ -5372,6 +5348,16 @@ void ufshcd_remove(struct ufs_hba *hba)
 }
 EXPORT_SYMBOL_GPL(ufshcd_remove);
 
+/**
+ * ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA)
+ * @hba: pointer to Host Bus Adapter (HBA)
+ */
+void ufshcd_dealloc_host(struct ufs_hba *hba)
+{
+       scsi_host_put(hba->host);
+}
+EXPORT_SYMBOL_GPL(ufshcd_dealloc_host);
+
 /**
  * ufshcd_set_dma_mask - Set dma mask based on the controller
  *                      addressing capability
@@ -5433,6 +5419,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
        if (!head || list_empty(head))
                goto out;
 
+       ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE);
+       if (ret)
+               return ret;
+
        list_for_each_entry(clki, head, list) {
                if (!IS_ERR_OR_NULL(clki->clk)) {
                        if (scale_up && clki->max_freq) {
@@ -5463,8 +5453,9 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
                dev_dbg(hba->dev, "%s: clk: %s, rate: %lu\n", __func__,
                                clki->name, clk_get_rate(clki->clk));
        }
-       if (hba->vops->clk_scale_notify)
-               hba->vops->clk_scale_notify(hba);
+
+       ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
+
 out:
        return ret;
 }
@@ -5619,13 +5610,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
                hba->is_irq_enabled = true;
        }
 
-       /* Enable SCSI tag mapping */
-       err = scsi_init_shared_tag_map(host, host->can_queue);
-       if (err) {
-               dev_err(hba->dev, "init shared queue failed\n");
-               goto exit_gating;
-       }
-
        err = scsi_add_host(host, hba->dev);
        if (err) {
                dev_err(hba->dev, "scsi_add_host failed\n");
index c40a0e78a6c4298cf437dc312f0a136dd78abfa9..2570d9477b3778c9505e616f72c22e0b30fad8be 100644 (file)
@@ -223,8 +223,10 @@ struct ufs_clk_info {
        bool enabled;
 };
 
-#define PRE_CHANGE      0
-#define POST_CHANGE     1
+enum ufs_notify_change_status {
+       PRE_CHANGE,
+       POST_CHANGE,
+};
 
 struct ufs_pa_layer_attr {
        u32 gear_rx;
@@ -259,22 +261,28 @@ struct ufs_pwr_mode_info {
  *                     to be set.
  * @suspend: called during host controller PM callback
  * @resume: called during host controller PM callback
+ * @dbg_register_dump: used to dump controller debug information
  */
 struct ufs_hba_variant_ops {
        const char *name;
        int     (*init)(struct ufs_hba *);
        void    (*exit)(struct ufs_hba *);
        u32     (*get_ufs_hci_version)(struct ufs_hba *);
-       void    (*clk_scale_notify)(struct ufs_hba *);
-       int     (*setup_clocks)(struct ufs_hba *, bool);
+       int     (*clk_scale_notify)(struct ufs_hba *, bool,
+                                   enum ufs_notify_change_status);
+       int     (*setup_clocks)(struct ufs_hba *, bool);
        int     (*setup_regulators)(struct ufs_hba *, bool);
-       int     (*hce_enable_notify)(struct ufs_hba *, bool);
-       int     (*link_startup_notify)(struct ufs_hba *, bool);
+       int     (*hce_enable_notify)(struct ufs_hba *,
+                                    enum ufs_notify_change_status);
+       int     (*link_startup_notify)(struct ufs_hba *,
+                                      enum ufs_notify_change_status);
        int     (*pwr_change_notify)(struct ufs_hba *,
-                                       bool, struct ufs_pa_layer_attr *,
+                                       enum ufs_notify_change_status status,
+                                       struct ufs_pa_layer_attr *,
                                        struct ufs_pa_layer_attr *);
        int     (*suspend)(struct ufs_hba *, enum ufs_pm_op);
        int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
+       void    (*dbg_register_dump)(struct ufs_hba *hba);
 };
 
 /* clock gating state  */
@@ -576,6 +584,7 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
 }
 
 int ufshcd_alloc_host(struct device *, struct ufs_hba **);
+void ufshcd_dealloc_host(struct ufs_hba *);
 int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int);
 void ufshcd_remove(struct ufs_hba *);
 
@@ -594,6 +603,27 @@ static inline void check_upiu_size(void)
                GENERAL_UPIU_REQUEST_SIZE + QUERY_DESC_MAX_SIZE);
 }
 
+/**
+ * ufshcd_set_variant - set variant specific data to the hba
+ * @hba - per adapter instance
+ * @variant - pointer to variant specific data
+ */
+static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
+{
+       BUG_ON(!hba);
+       hba->priv = variant;
+}
+
+/**
+ * ufshcd_get_variant - get variant specific data from the hba
+ * @hba - per adapter instance
+ */
+static inline void *ufshcd_get_variant(struct ufs_hba *hba)
+{
+       BUG_ON(!hba);
+       return hba->priv;
+}
+
 extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
 extern int ufshcd_runtime_resume(struct ufs_hba *hba);
 extern int ufshcd_runtime_idle(struct ufs_hba *hba);
@@ -653,4 +683,109 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
 
 int ufshcd_hold(struct ufs_hba *hba, bool async);
 void ufshcd_release(struct ufs_hba *hba);
+
+/* Wrapper functions for safely calling variant operations */
+static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
+{
+       if (hba->vops)
+               return hba->vops->name;
+       return "";
+}
+
+static inline int ufshcd_vops_init(struct ufs_hba *hba)
+{
+       if (hba->vops && hba->vops->init)
+               return hba->vops->init(hba);
+
+       return 0;
+}
+
+static inline void ufshcd_vops_exit(struct ufs_hba *hba)
+{
+       if (hba->vops && hba->vops->exit)
+               return hba->vops->exit(hba);
+}
+
+static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
+{
+       if (hba->vops && hba->vops->get_ufs_hci_version)
+               return hba->vops->get_ufs_hci_version(hba);
+
+       return ufshcd_readl(hba, REG_UFS_VERSION);
+}
+
+static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
+                       bool up, enum ufs_notify_change_status status)
+{
+       if (hba->vops && hba->vops->clk_scale_notify)
+               return hba->vops->clk_scale_notify(hba, up, status);
+       return 0;
+}
+
+static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on)
+{
+       if (hba->vops && hba->vops->setup_clocks)
+               return hba->vops->setup_clocks(hba, on);
+       return 0;
+}
+
+static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status)
+{
+       if (hba->vops && hba->vops->setup_regulators)
+               return hba->vops->setup_regulators(hba, status);
+
+       return 0;
+}
+
+static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
+                                               bool status)
+{
+       if (hba->vops && hba->vops->hce_enable_notify)
+               return hba->vops->hce_enable_notify(hba, status);
+
+       return 0;
+}
+static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
+                                               bool status)
+{
+       if (hba->vops && hba->vops->link_startup_notify)
+               return hba->vops->link_startup_notify(hba, status);
+
+       return 0;
+}
+
+static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
+                                 bool status,
+                                 struct ufs_pa_layer_attr *dev_max_params,
+                                 struct ufs_pa_layer_attr *dev_req_params)
+{
+       if (hba->vops && hba->vops->pwr_change_notify)
+               return hba->vops->pwr_change_notify(hba, status,
+                                       dev_max_params, dev_req_params);
+
+       return -ENOTSUPP;
+}
+
+static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+       if (hba->vops && hba->vops->suspend)
+               return hba->vops->suspend(hba, op);
+
+       return 0;
+}
+
+static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+       if (hba->vops && hba->vops->resume)
+               return hba->vops->resume(hba, op);
+
+       return 0;
+}
+
+static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
+{
+       if (hba->vops && hba->vops->dbg_register_dump)
+               hba->vops->dbg_register_dump(hba);
+}
+
 #endif /* End of Header */
index 25abd4eb7d102113d94c62bf7bbc1b8f935f0ca8..91a003011acfacb277e892b47c99771ceae80ffa 100644 (file)
@@ -34,7 +34,7 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
 
 static int __init sh_pm_runtime_init(void)
 {
-       if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
+       if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
                if (!of_find_compatible_node(NULL, NULL,
                                             "renesas,cpg-mstp-clocks"))
                        return 0;
index 9d5068248aa0486f147bbbc90f1f2ac495ad0378..0a4ea809a61b0cddb37fd6fc2b72e6047a343bf4 100644 (file)
@@ -23,6 +23,7 @@ config MTK_PMIC_WRAP
 config MTK_SCPSYS
        bool "MediaTek SCPSYS Support"
        depends on ARCH_MEDIATEK || COMPILE_TEST
+       default ARM64 && ARCH_MEDIATEK
        select REGMAP
        select MTK_INFRACFG
        select PM_GENERIC_DOMAINS if PM
index f3a0b6a4b54ef8093f2dbbabbcdd7c07de1cddbe..8c03a80b482ddac7c1e22ac4178772f7d29819ff 100644 (file)
@@ -1179,7 +1179,7 @@ static int knav_queue_setup_link_ram(struct knav_device *kdev)
 
                block++;
                if (!block->size)
-                       return 0;
+                       continue;
 
                dev_dbg(kdev->dev, "linkram1: phys:%x, virt:%p, size:%x\n",
                        block->phys, block->virt, block->size);
@@ -1519,9 +1519,9 @@ static int knav_queue_load_pdsp(struct knav_device *kdev,
 
        for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
                if (knav_acc_firmwares[i]) {
-                       ret = request_firmware(&fw,
-                                              knav_acc_firmwares[i],
-                                              kdev->dev);
+                       ret = request_firmware_direct(&fw,
+                                                     knav_acc_firmwares[i],
+                                                     kdev->dev);
                        if (!ret) {
                                found = true;
                                break;
index 6d5b38d6957852ee81caa09cb6e3c047c55d26b8..9d7f0004d2d7b25bcd7e67b345aaa4f3ad407d32 100644 (file)
@@ -18,7 +18,8 @@ source "drivers/staging/iio/resolver/Kconfig"
 source "drivers/staging/iio/trigger/Kconfig"
 
 config IIO_DUMMY_EVGEN
-       tristate
+       tristate
+       select IRQ_WORK
 
 config IIO_SIMPLE_DUMMY
        tristate "An example driver with no hardware requirements"
index d11c54b721860cccb0c6db82a6d9353787560896..b51f237cd817c9dc8fe668bb61ae708577bf8287 100644 (file)
@@ -76,7 +76,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
 
        if (mask == IIO_CHAN_INFO_RAW) {
                mutex_lock(&indio_dev->mlock);
-               clk_enable(info->clk);
+               clk_prepare_enable(info->clk);
                /* Measurement setup */
                __raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
                             LPC32XX_ADC_SELECT(info->adc_base));
@@ -84,7 +84,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
                __raw_writel(AD_PDN_CTRL | AD_STROBE,
                             LPC32XX_ADC_CTRL(info->adc_base));
                wait_for_completion(&info->completion); /* set by ISR */
-               clk_disable(info->clk);
+               clk_disable_unprepare(info->clk);
                *val = info->value;
                mutex_unlock(&indio_dev->mlock);
 
index e10c6ffa698a6f541ad4e40c7007ddc4852b50cd..9568bdb6319bb77a84d49544e77410182a528ad7 100644 (file)
 #include "wilc_wlan.h"
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/etherdevice.h>
 #define TAG_PARAM_OFFSET       (MAC_HDR_LEN + TIME_STAMP_LEN + \
                                                        BEACON_INTERVAL_LEN + CAP_INFO_LEN)
-#define ADDR1 4
-#define ADDR2 10
-#define ADDR3 16
 
 /* Basic Frame Type Codes (2-bit) */
 enum basic_frame_type {
@@ -175,32 +171,38 @@ static inline u8 get_from_ds(u8 *header)
        return ((header[1] & 0x02) >> 1);
 }
 
+/* This function extracts the MAC Address in 'address1' field of the MAC     */
+/* header and updates the MAC Address in the allocated 'addr' variable.      */
+static inline void get_address1(u8 *pu8msa, u8 *addr)
+{
+       memcpy(addr, pu8msa + 4, 6);
+}
+
+/* This function extracts the MAC Address in 'address2' field of the MAC     */
+/* header and updates the MAC Address in the allocated 'addr' variable.      */
+static inline void get_address2(u8 *pu8msa, u8 *addr)
+{
+       memcpy(addr, pu8msa + 10, 6);
+}
+
+/* This function extracts the MAC Address in 'address3' field of the MAC     */
+/* header and updates the MAC Address in the allocated 'addr' variable.      */
+static inline void get_address3(u8 *pu8msa, u8 *addr)
+{
+       memcpy(addr, pu8msa + 16, 6);
+}
+
 /* This function extracts the BSSID from the incoming WLAN packet based on   */
-/* the 'from ds' bit, and updates the MAC Address in the allocated 'data'    */
+/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr'    */
 /* variable.                                                                 */
 static inline void get_BSSID(u8 *data, u8 *bssid)
 {
        if (get_from_ds(data) == 1)
-               /*
-                * Extract the MAC Address in 'address2' field of the MAC
-                * header and update the MAC Address in the allocated 'data'
-                *  variable.
-                */
-               ether_addr_copy(data, bssid + ADDR2);
+               get_address2(data, bssid);
        else if (get_to_ds(data) == 1)
-               /*
-                * Extract the MAC Address in 'address1' field of the MAC
-                * header and update the MAC Address in the allocated 'data'
-                * variable.
-                */
-               ether_addr_copy(data, bssid + ADDR1);
+               get_address1(data, bssid);
        else
-               /*
-                * Extract the MAC Address in 'address3' field of the MAC
-                * header and update the MAC Address in the allocated 'data'
-                * variable.
-                */
-               ether_addr_copy(data, bssid + ADDR3);
+               get_address3(data, bssid);
 }
 
 /* This function extracts the SSID from a beacon/probe response frame        */
index c7461d770d3a8bff4ba0d4c64067654cf53512ca..255204cc43e6218ff7caa6725d7430f300a4d571 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/inet.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 #include <target/iscsi/iscsi_transport.h>
 
 #include <target/iscsi/iscsi_target_core.h>
 #include "iscsi_target.h"
 #include <target/iscsi/iscsi_target_stat.h>
 
-struct lio_target_configfs_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(void *, char *);
-       ssize_t (*store)(void *, const char *, size_t);
-};
 
 /* Start items for lio_target_portal_cit */
 
-static ssize_t lio_target_np_show_sctp(
-       struct se_tpg_np *se_tpg_np,
-       char *page)
+static inline struct iscsi_tpg_np *to_iscsi_tpg_np(struct config_item *item)
+{
+       return container_of(to_tpg_np(item), struct iscsi_tpg_np, se_tpg_np);
+}
+
+static ssize_t lio_target_np_sctp_show(struct config_item *item, char *page)
 {
-       struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
-                               struct iscsi_tpg_np, se_tpg_np);
+       struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
        struct iscsi_tpg_np *tpg_np_sctp;
        ssize_t rb;
 
@@ -63,15 +58,12 @@ static ssize_t lio_target_np_show_sctp(
        return rb;
 }
 
-static ssize_t lio_target_np_store_sctp(
-       struct se_tpg_np *se_tpg_np,
-       const char *page,
-       size_t count)
+static ssize_t lio_target_np_sctp_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
        struct iscsi_np *np;
        struct iscsi_portal_group *tpg;
-       struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
-                               struct iscsi_tpg_np, se_tpg_np);
        struct iscsi_tpg_np *tpg_np_sctp = NULL;
        u32 op;
        int ret;
@@ -119,14 +111,9 @@ static ssize_t lio_target_np_store_sctp(
        return -EINVAL;
 }
 
-TF_NP_BASE_ATTR(lio_target, sctp, S_IRUGO | S_IWUSR);
-
-static ssize_t lio_target_np_show_iser(
-       struct se_tpg_np *se_tpg_np,
-       char *page)
+static ssize_t lio_target_np_iser_show(struct config_item *item, char *page)
 {
-       struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
-                               struct iscsi_tpg_np, se_tpg_np);
+       struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
        struct iscsi_tpg_np *tpg_np_iser;
        ssize_t rb;
 
@@ -139,15 +126,12 @@ static ssize_t lio_target_np_show_iser(
        return rb;
 }
 
-static ssize_t lio_target_np_store_iser(
-       struct se_tpg_np *se_tpg_np,
-       const char *page,
-       size_t count)
+static ssize_t lio_target_np_iser_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct iscsi_tpg_np *tpg_np = to_iscsi_tpg_np(item);
        struct iscsi_np *np;
        struct iscsi_portal_group *tpg;
-       struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
-                               struct iscsi_tpg_np, se_tpg_np);
        struct iscsi_tpg_np *tpg_np_iser = NULL;
        char *endptr;
        u32 op;
@@ -198,11 +182,12 @@ static ssize_t lio_target_np_store_iser(
        return rc;
 }
 
-TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(lio_target_np_, sctp);
+CONFIGFS_ATTR(lio_target_np_, iser);
 
 static struct configfs_attribute *lio_target_portal_attrs[] = {
-       &lio_target_np_sctp.attr,
-       &lio_target_np_iser.attr,
+       &lio_target_np_attr_sctp,
+       &lio_target_np_attr_iser,
        NULL,
 };
 
@@ -360,22 +345,21 @@ static void lio_target_call_delnpfromtpg(
 
 /* Start items for lio_target_nacl_attrib_cit */
 
-#define DEF_NACL_ATTRIB(name)                                          \
-static ssize_t iscsi_nacl_attrib_show_##name(                          \
-       struct se_node_acl *se_nacl,                                    \
-       char *page)                                                     \
+#define ISCSI_NACL_ATTR(name)                                          \
+static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\
+               char *page)                                             \
 {                                                                      \
+       struct se_node_acl *se_nacl = attrib_to_nacl(item);             \
        struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
                                        se_node_acl);                   \
                                                                        \
        return sprintf(page, "%u\n", nacl->node_attrib.name);           \
 }                                                                      \
                                                                        \
-static ssize_t iscsi_nacl_attrib_store_##name(                         \
-       struct se_node_acl *se_nacl,                                    \
-       const char *page,                                               \
-       size_t count)                                                   \
+static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\
+               const char *page, size_t count)                         \
 {                                                                      \
+       struct se_node_acl *se_nacl = attrib_to_nacl(item);             \
        struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \
                                        se_node_acl);                   \
        u32 val;                                                        \
@@ -389,59 +373,28 @@ static ssize_t iscsi_nacl_attrib_store_##name(                            \
                return ret;                                             \
                                                                        \
        return count;                                                   \
-}
+}                                                                      \
+                                                                       \
+CONFIGFS_ATTR(iscsi_nacl_attrib_, name)
 
-#define NACL_ATTR(_name, _mode) TF_NACL_ATTRIB_ATTR(iscsi, _name, _mode);
-/*
- * Define iscsi_node_attrib_s_dataout_timeout
- */
-DEF_NACL_ATTRIB(dataout_timeout);
-NACL_ATTR(dataout_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_dataout_timeout_retries
- */
-DEF_NACL_ATTRIB(dataout_timeout_retries);
-NACL_ATTR(dataout_timeout_retries, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_default_erl
- */
-DEF_NACL_ATTRIB(default_erl);
-NACL_ATTR(default_erl, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_nopin_timeout
- */
-DEF_NACL_ATTRIB(nopin_timeout);
-NACL_ATTR(nopin_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_nopin_response_timeout
- */
-DEF_NACL_ATTRIB(nopin_response_timeout);
-NACL_ATTR(nopin_response_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_datain_pdu_offsets
- */
-DEF_NACL_ATTRIB(random_datain_pdu_offsets);
-NACL_ATTR(random_datain_pdu_offsets, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_datain_seq_offsets
- */
-DEF_NACL_ATTRIB(random_datain_seq_offsets);
-NACL_ATTR(random_datain_seq_offsets, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_node_attrib_s_random_r2t_offsets
- */
-DEF_NACL_ATTRIB(random_r2t_offsets);
-NACL_ATTR(random_r2t_offsets, S_IRUGO | S_IWUSR);
+ISCSI_NACL_ATTR(dataout_timeout);
+ISCSI_NACL_ATTR(dataout_timeout_retries);
+ISCSI_NACL_ATTR(default_erl);
+ISCSI_NACL_ATTR(nopin_timeout);
+ISCSI_NACL_ATTR(nopin_response_timeout);
+ISCSI_NACL_ATTR(random_datain_pdu_offsets);
+ISCSI_NACL_ATTR(random_datain_seq_offsets);
+ISCSI_NACL_ATTR(random_r2t_offsets);
 
 static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = {
-       &iscsi_nacl_attrib_dataout_timeout.attr,
-       &iscsi_nacl_attrib_dataout_timeout_retries.attr,
-       &iscsi_nacl_attrib_default_erl.attr,
-       &iscsi_nacl_attrib_nopin_timeout.attr,
-       &iscsi_nacl_attrib_nopin_response_timeout.attr,
-       &iscsi_nacl_attrib_random_datain_pdu_offsets.attr,
-       &iscsi_nacl_attrib_random_datain_seq_offsets.attr,
-       &iscsi_nacl_attrib_random_r2t_offsets.attr,
+       &iscsi_nacl_attrib_attr_dataout_timeout,
+       &iscsi_nacl_attrib_attr_dataout_timeout_retries,
+       &iscsi_nacl_attrib_attr_default_erl,
+       &iscsi_nacl_attrib_attr_nopin_timeout,
+       &iscsi_nacl_attrib_attr_nopin_response_timeout,
+       &iscsi_nacl_attrib_attr_random_datain_pdu_offsets,
+       &iscsi_nacl_attrib_attr_random_datain_seq_offsets,
+       &iscsi_nacl_attrib_attr_random_r2t_offsets,
        NULL,
 };
 
@@ -450,7 +403,7 @@ static struct configfs_attribute *lio_target_nacl_attrib_attrs[] = {
 /* Start items for lio_target_nacl_auth_cit */
 
 #define __DEF_NACL_AUTH_STR(prefix, name, flags)                       \
-static ssize_t __iscsi_##prefix##_show_##name(                         \
+static ssize_t __iscsi_##prefix##_##name##_show(                       \
        struct iscsi_node_acl *nacl,                                    \
        char *page)                                                     \
 {                                                                      \
@@ -461,7 +414,7 @@ static ssize_t __iscsi_##prefix##_show_##name(                              \
        return snprintf(page, PAGE_SIZE, "%s\n", auth->name);           \
 }                                                                      \
                                                                        \
-static ssize_t __iscsi_##prefix##_store_##name(                                \
+static ssize_t __iscsi_##prefix##_##name##_store(                      \
        struct iscsi_node_acl *nacl,                                    \
        const char *page,                                               \
        size_t count)                                                   \
@@ -487,8 +440,35 @@ static ssize_t __iscsi_##prefix##_store_##name(                            \
        return count;                                                   \
 }
 
+#define DEF_NACL_AUTH_STR(name, flags)                                 \
+       __DEF_NACL_AUTH_STR(nacl_auth, name, flags)                     \
+static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \
+               char *page)                                             \
+{                                                                      \
+       struct se_node_acl *nacl = auth_to_nacl(item);                  \
+       return __iscsi_nacl_auth_##name##_show(container_of(nacl,       \
+                       struct iscsi_node_acl, se_node_acl), page);     \
+}                                                                      \
+static ssize_t iscsi_nacl_auth_##name##_store(struct config_item *item,        \
+               const char *page, size_t count)                         \
+{                                                                      \
+       struct se_node_acl *nacl = auth_to_nacl(item);                  \
+       return __iscsi_nacl_auth_##name##_store(container_of(nacl,      \
+                       struct iscsi_node_acl, se_node_acl), page, count); \
+}                                                                      \
+                                                                       \
+CONFIGFS_ATTR(iscsi_nacl_auth_, name)
+
+/*
+ * One-way authentication userid
+ */
+DEF_NACL_AUTH_STR(userid, NAF_USERID_SET);
+DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+
 #define __DEF_NACL_AUTH_INT(prefix, name)                              \
-static ssize_t __iscsi_##prefix##_show_##name(                         \
+static ssize_t __iscsi_##prefix##_##name##_show(                               \
        struct iscsi_node_acl *nacl,                                    \
        char *page)                                                     \
 {                                                                      \
@@ -500,69 +480,26 @@ static ssize_t __iscsi_##prefix##_show_##name(                            \
        return snprintf(page, PAGE_SIZE, "%d\n", auth->name);           \
 }
 
-#define DEF_NACL_AUTH_STR(name, flags)                                 \
-       __DEF_NACL_AUTH_STR(nacl_auth, name, flags)                     \
-static ssize_t iscsi_nacl_auth_show_##name(                            \
-       struct se_node_acl *nacl,                                       \
-       char *page)                                                     \
-{                                                                      \
-       return __iscsi_nacl_auth_show_##name(container_of(nacl,         \
-                       struct iscsi_node_acl, se_node_acl), page);             \
-}                                                                      \
-static ssize_t iscsi_nacl_auth_store_##name(                           \
-       struct se_node_acl *nacl,                                       \
-       const char *page,                                               \
-       size_t count)                                                   \
-{                                                                      \
-       return __iscsi_nacl_auth_store_##name(container_of(nacl,        \
-                       struct iscsi_node_acl, se_node_acl), page, count);      \
-}
-
 #define DEF_NACL_AUTH_INT(name)                                                \
        __DEF_NACL_AUTH_INT(nacl_auth, name)                            \
-static ssize_t iscsi_nacl_auth_show_##name(                            \
-       struct se_node_acl *nacl,                                       \
-       char *page)                                                     \
+static ssize_t iscsi_nacl_auth_##name##_show(struct config_item *item, \
+               char *page)                                             \
 {                                                                      \
-       return __iscsi_nacl_auth_show_##name(container_of(nacl,         \
-                       struct iscsi_node_acl, se_node_acl), page);             \
-}
-
-#define AUTH_ATTR(_name, _mode)        TF_NACL_AUTH_ATTR(iscsi, _name, _mode);
-#define AUTH_ATTR_RO(_name) TF_NACL_AUTH_ATTR_RO(iscsi, _name);
+       struct se_node_acl *nacl = auth_to_nacl(item);                  \
+       return __iscsi_nacl_auth_##name##_show(container_of(nacl,       \
+                       struct iscsi_node_acl, se_node_acl), page);     \
+}                                                                      \
+                                                                       \
+CONFIGFS_ATTR_RO(iscsi_nacl_auth_, name)
 
-/*
- * One-way authentication userid
- */
-DEF_NACL_AUTH_STR(userid, NAF_USERID_SET);
-AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- * One-way authentication password
- */
-DEF_NACL_AUTH_STR(password, NAF_PASSWORD_SET);
-AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- * Enforce mutual authentication
- */
 DEF_NACL_AUTH_INT(authenticate_target);
-AUTH_ATTR_RO(authenticate_target);
-/*
- * Mutual authentication userid
- */
-DEF_NACL_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- * Mutual authentication password
- */
-DEF_NACL_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *lio_target_nacl_auth_attrs[] = {
-       &iscsi_nacl_auth_userid.attr,
-       &iscsi_nacl_auth_password.attr,
-       &iscsi_nacl_auth_authenticate_target.attr,
-       &iscsi_nacl_auth_userid_mutual.attr,
-       &iscsi_nacl_auth_password_mutual.attr,
+       &iscsi_nacl_auth_attr_userid,
+       &iscsi_nacl_auth_attr_password,
+       &iscsi_nacl_auth_attr_authenticate_target,
+       &iscsi_nacl_auth_attr_userid_mutual,
+       &iscsi_nacl_auth_attr_password_mutual,
        NULL,
 };
 
@@ -570,11 +507,11 @@ static struct configfs_attribute *lio_target_nacl_auth_attrs[] = {
 
 /* Start items for lio_target_nacl_param_cit */
 
-#define DEF_NACL_PARAM(name)                                           \
-static ssize_t iscsi_nacl_param_show_##name(                           \
-       struct se_node_acl *se_nacl,                                    \
-       char *page)                                                     \
+#define ISCSI_NACL_PARAM(name)                                         \
+static ssize_t iscsi_nacl_param_##name##_show(struct config_item *item,        \
+               char *page)                                             \
 {                                                                      \
+       struct se_node_acl *se_nacl = param_to_nacl(item);              \
        struct iscsi_session *sess;                                     \
        struct se_session *se_sess;                                     \
        ssize_t rb;                                                     \
@@ -592,55 +529,34 @@ static ssize_t iscsi_nacl_param_show_##name(                              \
        spin_unlock_bh(&se_nacl->nacl_sess_lock);                       \
                                                                        \
        return rb;                                                      \
-}
-
-#define NACL_PARAM_ATTR(_name) TF_NACL_PARAM_ATTR_RO(iscsi, _name);
-
-DEF_NACL_PARAM(MaxConnections);
-NACL_PARAM_ATTR(MaxConnections);
-
-DEF_NACL_PARAM(InitialR2T);
-NACL_PARAM_ATTR(InitialR2T);
-
-DEF_NACL_PARAM(ImmediateData);
-NACL_PARAM_ATTR(ImmediateData);
-
-DEF_NACL_PARAM(MaxBurstLength);
-NACL_PARAM_ATTR(MaxBurstLength);
-
-DEF_NACL_PARAM(FirstBurstLength);
-NACL_PARAM_ATTR(FirstBurstLength);
-
-DEF_NACL_PARAM(DefaultTime2Wait);
-NACL_PARAM_ATTR(DefaultTime2Wait);
-
-DEF_NACL_PARAM(DefaultTime2Retain);
-NACL_PARAM_ATTR(DefaultTime2Retain);
-
-DEF_NACL_PARAM(MaxOutstandingR2T);
-NACL_PARAM_ATTR(MaxOutstandingR2T);
-
-DEF_NACL_PARAM(DataPDUInOrder);
-NACL_PARAM_ATTR(DataPDUInOrder);
-
-DEF_NACL_PARAM(DataSequenceInOrder);
-NACL_PARAM_ATTR(DataSequenceInOrder);
-
-DEF_NACL_PARAM(ErrorRecoveryLevel);
-NACL_PARAM_ATTR(ErrorRecoveryLevel);
+}                                                                      \
+                                                                       \
+CONFIGFS_ATTR_RO(iscsi_nacl_param_, name)
+
+ISCSI_NACL_PARAM(MaxConnections);
+ISCSI_NACL_PARAM(InitialR2T);
+ISCSI_NACL_PARAM(ImmediateData);
+ISCSI_NACL_PARAM(MaxBurstLength);
+ISCSI_NACL_PARAM(FirstBurstLength);
+ISCSI_NACL_PARAM(DefaultTime2Wait);
+ISCSI_NACL_PARAM(DefaultTime2Retain);
+ISCSI_NACL_PARAM(MaxOutstandingR2T);
+ISCSI_NACL_PARAM(DataPDUInOrder);
+ISCSI_NACL_PARAM(DataSequenceInOrder);
+ISCSI_NACL_PARAM(ErrorRecoveryLevel);
 
 static struct configfs_attribute *lio_target_nacl_param_attrs[] = {
-       &iscsi_nacl_param_MaxConnections.attr,
-       &iscsi_nacl_param_InitialR2T.attr,
-       &iscsi_nacl_param_ImmediateData.attr,
-       &iscsi_nacl_param_MaxBurstLength.attr,
-       &iscsi_nacl_param_FirstBurstLength.attr,
-       &iscsi_nacl_param_DefaultTime2Wait.attr,
-       &iscsi_nacl_param_DefaultTime2Retain.attr,
-       &iscsi_nacl_param_MaxOutstandingR2T.attr,
-       &iscsi_nacl_param_DataPDUInOrder.attr,
-       &iscsi_nacl_param_DataSequenceInOrder.attr,
-       &iscsi_nacl_param_ErrorRecoveryLevel.attr,
+       &iscsi_nacl_param_attr_MaxConnections,
+       &iscsi_nacl_param_attr_InitialR2T,
+       &iscsi_nacl_param_attr_ImmediateData,
+       &iscsi_nacl_param_attr_MaxBurstLength,
+       &iscsi_nacl_param_attr_FirstBurstLength,
+       &iscsi_nacl_param_attr_DefaultTime2Wait,
+       &iscsi_nacl_param_attr_DefaultTime2Retain,
+       &iscsi_nacl_param_attr_MaxOutstandingR2T,
+       &iscsi_nacl_param_attr_DataPDUInOrder,
+       &iscsi_nacl_param_attr_DataSequenceInOrder,
+       &iscsi_nacl_param_attr_ErrorRecoveryLevel,
        NULL,
 };
 
@@ -648,10 +564,9 @@ static struct configfs_attribute *lio_target_nacl_param_attrs[] = {
 
 /* Start items for lio_target_acl_cit */
 
-static ssize_t lio_target_nacl_show_info(
-       struct se_node_acl *se_nacl,
-       char *page)
+static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct iscsi_session *sess;
        struct iscsi_conn *conn;
        struct se_session *se_sess;
@@ -766,20 +681,16 @@ static ssize_t lio_target_nacl_show_info(
        return rb;
 }
 
-TF_NACL_BASE_ATTR_RO(lio_target, info);
-
-static ssize_t lio_target_nacl_show_cmdsn_depth(
-       struct se_node_acl *se_nacl,
-       char *page)
+static ssize_t lio_target_nacl_cmdsn_depth_show(struct config_item *item,
+               char *page)
 {
-       return sprintf(page, "%u\n", se_nacl->queue_depth);
+       return sprintf(page, "%u\n", acl_to_nacl(item)->queue_depth);
 }
 
-static ssize_t lio_target_nacl_store_cmdsn_depth(
-       struct se_node_acl *se_nacl,
-       const char *page,
-       size_t count)
+static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct se_portal_group *se_tpg = se_nacl->se_tpg;
        struct iscsi_portal_group *tpg = container_of(se_tpg,
                        struct iscsi_portal_group, tpg_se_tpg);
@@ -829,20 +740,15 @@ static ssize_t lio_target_nacl_store_cmdsn_depth(
        return (!ret) ? count : (ssize_t)ret;
 }
 
-TF_NACL_BASE_ATTR(lio_target, cmdsn_depth, S_IRUGO | S_IWUSR);
-
-static ssize_t lio_target_nacl_show_tag(
-       struct se_node_acl *se_nacl,
-       char *page)
+static ssize_t lio_target_nacl_tag_show(struct config_item *item, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%s", se_nacl->acl_tag);
+       return snprintf(page, PAGE_SIZE, "%s", acl_to_nacl(item)->acl_tag);
 }
 
-static ssize_t lio_target_nacl_store_tag(
-       struct se_node_acl *se_nacl,
-       const char *page,
-       size_t count)
+static ssize_t lio_target_nacl_tag_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        int ret;
 
        ret = core_tpg_set_initiator_node_tag(se_nacl->se_tpg, se_nacl, page);
@@ -852,12 +758,14 @@ static ssize_t lio_target_nacl_store_tag(
        return count;
 }
 
-TF_NACL_BASE_ATTR(lio_target, tag, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR_RO(lio_target_nacl_, info);
+CONFIGFS_ATTR(lio_target_nacl_, cmdsn_depth);
+CONFIGFS_ATTR(lio_target_nacl_, tag);
 
 static struct configfs_attribute *lio_target_initiator_attrs[] = {
-       &lio_target_nacl_info.attr,
-       &lio_target_nacl_cmdsn_depth.attr,
-       &lio_target_nacl_tag.attr,
+       &lio_target_nacl_attr_info,
+       &lio_target_nacl_attr_cmdsn_depth,
+       &lio_target_nacl_attr_tag,
        NULL,
 };
 
@@ -907,10 +815,10 @@ static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl)
 
 #define DEF_TPG_ATTRIB(name)                                           \
                                                                        \
-static ssize_t iscsi_tpg_attrib_show_##name(                           \
-       struct se_portal_group *se_tpg,                         \
-       char *page)                                                     \
+static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item,        \
+               char *page)                                             \
 {                                                                      \
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);           \
        struct iscsi_portal_group *tpg = container_of(se_tpg,           \
                        struct iscsi_portal_group, tpg_se_tpg); \
        ssize_t rb;                                                     \
@@ -923,11 +831,10 @@ static ssize_t iscsi_tpg_attrib_show_##name(                              \
        return rb;                                                      \
 }                                                                      \
                                                                        \
-static ssize_t iscsi_tpg_attrib_store_##name(                          \
-       struct se_portal_group *se_tpg,                         \
-       const char *page,                                               \
-       size_t count)                                                   \
+static ssize_t iscsi_tpg_attrib_##name##_store(struct config_item *item,\
+               const char *page, size_t count)                         \
 {                                                                      \
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);           \
        struct iscsi_portal_group *tpg = container_of(se_tpg,           \
                        struct iscsi_portal_group, tpg_se_tpg); \
        u32 val;                                                        \
@@ -948,90 +855,37 @@ static ssize_t iscsi_tpg_attrib_store_##name(                             \
 out:                                                                   \
        iscsit_put_tpg(tpg);                                            \
        return ret;                                                     \
-}
-
-#define TPG_ATTR(_name, _mode) TF_TPG_ATTRIB_ATTR(iscsi, _name, _mode);
+}                                                                      \
+CONFIGFS_ATTR(iscsi_tpg_attrib_, name)
 
-/*
- * Define iscsi_tpg_attrib_s_authentication
- */
 DEF_TPG_ATTRIB(authentication);
-TPG_ATTR(authentication, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_login_timeout
- */
 DEF_TPG_ATTRIB(login_timeout);
-TPG_ATTR(login_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_netif_timeout
- */
 DEF_TPG_ATTRIB(netif_timeout);
-TPG_ATTR(netif_timeout, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_generate_node_acls
- */
 DEF_TPG_ATTRIB(generate_node_acls);
-TPG_ATTR(generate_node_acls, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_default_cmdsn_depth
- */
 DEF_TPG_ATTRIB(default_cmdsn_depth);
-TPG_ATTR(default_cmdsn_depth, S_IRUGO | S_IWUSR);
-/*
- Define iscsi_tpg_attrib_s_cache_dynamic_acls
- */
 DEF_TPG_ATTRIB(cache_dynamic_acls);
-TPG_ATTR(cache_dynamic_acls, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_demo_mode_write_protect
- */
 DEF_TPG_ATTRIB(demo_mode_write_protect);
-TPG_ATTR(demo_mode_write_protect, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_prod_mode_write_protect
- */
 DEF_TPG_ATTRIB(prod_mode_write_protect);
-TPG_ATTR(prod_mode_write_protect, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_demo_mode_discovery,
- */
 DEF_TPG_ATTRIB(demo_mode_discovery);
-TPG_ATTR(demo_mode_discovery, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_default_erl
- */
 DEF_TPG_ATTRIB(default_erl);
-TPG_ATTR(default_erl, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_t10_pi
- */
 DEF_TPG_ATTRIB(t10_pi);
-TPG_ATTR(t10_pi, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_fabric_prot_type
- */
 DEF_TPG_ATTRIB(fabric_prot_type);
-TPG_ATTR(fabric_prot_type, S_IRUGO | S_IWUSR);
-/*
- * Define iscsi_tpg_attrib_s_tpg_enabled_sendtargets
- */
 DEF_TPG_ATTRIB(tpg_enabled_sendtargets);
-TPG_ATTR(tpg_enabled_sendtargets, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
-       &iscsi_tpg_attrib_authentication.attr,
-       &iscsi_tpg_attrib_login_timeout.attr,
-       &iscsi_tpg_attrib_netif_timeout.attr,
-       &iscsi_tpg_attrib_generate_node_acls.attr,
-       &iscsi_tpg_attrib_default_cmdsn_depth.attr,
-       &iscsi_tpg_attrib_cache_dynamic_acls.attr,
-       &iscsi_tpg_attrib_demo_mode_write_protect.attr,
-       &iscsi_tpg_attrib_prod_mode_write_protect.attr,
-       &iscsi_tpg_attrib_demo_mode_discovery.attr,
-       &iscsi_tpg_attrib_default_erl.attr,
-       &iscsi_tpg_attrib_t10_pi.attr,
-       &iscsi_tpg_attrib_fabric_prot_type.attr,
-       &iscsi_tpg_attrib_tpg_enabled_sendtargets.attr,
+       &iscsi_tpg_attrib_attr_authentication,
+       &iscsi_tpg_attrib_attr_login_timeout,
+       &iscsi_tpg_attrib_attr_netif_timeout,
+       &iscsi_tpg_attrib_attr_generate_node_acls,
+       &iscsi_tpg_attrib_attr_default_cmdsn_depth,
+       &iscsi_tpg_attrib_attr_cache_dynamic_acls,
+       &iscsi_tpg_attrib_attr_demo_mode_write_protect,
+       &iscsi_tpg_attrib_attr_prod_mode_write_protect,
+       &iscsi_tpg_attrib_attr_demo_mode_discovery,
+       &iscsi_tpg_attrib_attr_default_erl,
+       &iscsi_tpg_attrib_attr_t10_pi,
+       &iscsi_tpg_attrib_attr_fabric_prot_type,
+       &iscsi_tpg_attrib_attr_tpg_enabled_sendtargets,
        NULL,
 };
 
@@ -1040,9 +894,8 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
 /* Start items for lio_target_tpg_auth_cit */
 
 #define __DEF_TPG_AUTH_STR(prefix, name, flags)                                        \
-static ssize_t __iscsi_##prefix##_show_##name(                                 \
-       struct se_portal_group *se_tpg,                                         \
-       char *page)                                                             \
+static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg,        \
+               char *page)                                                     \
 {                                                                              \
        struct iscsi_portal_group *tpg = container_of(se_tpg,                   \
                                struct iscsi_portal_group, tpg_se_tpg);         \
@@ -1054,10 +907,8 @@ static ssize_t __iscsi_##prefix##_show_##name(                                    \
        return snprintf(page, PAGE_SIZE, "%s\n", auth->name);                   \
 }                                                                              \
                                                                                \
-static ssize_t __iscsi_##prefix##_store_##name(                                        \
-       struct se_portal_group *se_tpg,                                         \
-       const char *page,                                                       \
-       size_t count)                                                           \
+static ssize_t __iscsi_##prefix##_##name##_store(struct se_portal_group *se_tpg,\
+               const char *page, size_t count)                                 \
 {                                                                              \
        struct iscsi_portal_group *tpg = container_of(se_tpg,                   \
                                struct iscsi_portal_group, tpg_se_tpg);         \
@@ -1081,10 +932,31 @@ static ssize_t __iscsi_##prefix##_store_##name(                                  \
        return count;                                                           \
 }
 
+#define DEF_TPG_AUTH_STR(name, flags)                                          \
+       __DEF_TPG_AUTH_STR(tpg_auth, name, flags)                               \
+static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item,          \
+               char *page)                                                     \
+{                                                                              \
+       return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page);         \
+}                                                                              \
+                                                                               \
+static ssize_t iscsi_tpg_auth_##name##_store(struct config_item *item,         \
+               const char *page, size_t count)                                 \
+{                                                                              \
+       return __iscsi_tpg_auth_##name##_store(auth_to_tpg(item), page, count); \
+}                                                                              \
+                                                                               \
+CONFIGFS_ATTR(iscsi_tpg_auth_, name);
+
+
+DEF_TPG_AUTH_STR(userid, NAF_USERID_SET);
+DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
+
 #define __DEF_TPG_AUTH_INT(prefix, name)                                       \
-static ssize_t __iscsi_##prefix##_show_##name(                                 \
-       struct se_portal_group *se_tpg,                                         \
-       char *page)                                                             \
+static ssize_t __iscsi_##prefix##_##name##_show(struct se_portal_group *se_tpg,        \
+               char *page)                                                             \
 {                                                                              \
        struct iscsi_portal_group *tpg = container_of(se_tpg,                   \
                                struct iscsi_portal_group, tpg_se_tpg);         \
@@ -1096,67 +968,23 @@ static ssize_t __iscsi_##prefix##_show_##name(                                   \
        return snprintf(page, PAGE_SIZE, "%d\n", auth->name);                   \
 }
 
-#define DEF_TPG_AUTH_STR(name, flags)                                          \
-       __DEF_TPG_AUTH_STR(tpg_auth, name, flags)                               \
-static ssize_t iscsi_tpg_auth_show_##name(                                     \
-       struct se_portal_group *se_tpg,                                         \
-       char *page)                                                             \
-{                                                                              \
-       return __iscsi_tpg_auth_show_##name(se_tpg, page);                      \
-}                                                                              \
-                                                                               \
-static ssize_t iscsi_tpg_auth_store_##name(                                    \
-       struct se_portal_group *se_tpg,                                         \
-       const char *page,                                                       \
-       size_t count)                                                           \
-{                                                                              \
-       return __iscsi_tpg_auth_store_##name(se_tpg, page, count);              \
-}
-
 #define DEF_TPG_AUTH_INT(name)                                                 \
        __DEF_TPG_AUTH_INT(tpg_auth, name)                                      \
-static ssize_t iscsi_tpg_auth_show_##name(                                     \
-       struct se_portal_group *se_tpg,                                         \
-       char *page)                                                             \
+static ssize_t iscsi_tpg_auth_##name##_show(struct config_item *item,          \
+               char *page) \
 {                                                                              \
-       return __iscsi_tpg_auth_show_##name(se_tpg, page);                      \
-}
-
-#define TPG_AUTH_ATTR(_name, _mode) TF_TPG_AUTH_ATTR(iscsi, _name, _mode);
-#define TPG_AUTH_ATTR_RO(_name) TF_TPG_AUTH_ATTR_RO(iscsi, _name);
+       return __iscsi_tpg_auth_##name##_show(auth_to_tpg(item), page);         \
+}                                                                              \
+CONFIGFS_ATTR_RO(iscsi_tpg_auth_, name);
 
-/*
- *  * One-way authentication userid
- *   */
-DEF_TPG_AUTH_STR(userid, NAF_USERID_SET);
-TPG_AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- *  * One-way authentication password
- *   */
-DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET);
-TPG_AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- *  * Enforce mutual authentication
- *   */
 DEF_TPG_AUTH_INT(authenticate_target);
-TPG_AUTH_ATTR_RO(authenticate_target);
-/*
- *  * Mutual authentication userid
- *   */
-DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-TPG_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- *  * Mutual authentication password
- *   */
-DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-TPG_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *lio_target_tpg_auth_attrs[] = {
-       &iscsi_tpg_auth_userid.attr,
-       &iscsi_tpg_auth_password.attr,
-       &iscsi_tpg_auth_authenticate_target.attr,
-       &iscsi_tpg_auth_userid_mutual.attr,
-       &iscsi_tpg_auth_password_mutual.attr,
+       &iscsi_tpg_auth_attr_userid,
+       &iscsi_tpg_auth_attr_password,
+       &iscsi_tpg_auth_attr_authenticate_target,
+       &iscsi_tpg_auth_attr_userid_mutual,
+       &iscsi_tpg_auth_attr_password_mutual,
        NULL,
 };
 
@@ -1165,10 +993,10 @@ static struct configfs_attribute *lio_target_tpg_auth_attrs[] = {
 /* Start items for lio_target_tpg_param_cit */
 
 #define DEF_TPG_PARAM(name)                                            \
-static ssize_t iscsi_tpg_param_show_##name(                            \
-       struct se_portal_group *se_tpg,                                 \
-       char *page)                                                     \
+static ssize_t iscsi_tpg_param_##name##_show(struct config_item *item, \
+               char *page)                                             \
 {                                                                      \
+       struct se_portal_group *se_tpg = param_to_tpg(item);            \
        struct iscsi_portal_group *tpg = container_of(se_tpg,           \
                        struct iscsi_portal_group, tpg_se_tpg);         \
        struct iscsi_param *param;                                      \
@@ -1188,11 +1016,10 @@ static ssize_t iscsi_tpg_param_show_##name(                             \
        iscsit_put_tpg(tpg);                                            \
        return rb;                                                      \
 }                                                                      \
-static ssize_t iscsi_tpg_param_store_##name(                           \
-       struct se_portal_group *se_tpg,                         \
-       const char *page,                                               \
-       size_t count)                                                   \
+static ssize_t iscsi_tpg_param_##name##_store(struct config_item *item, \
+               const char *page, size_t count)                         \
 {                                                                      \
+       struct se_portal_group *se_tpg = param_to_tpg(item);            \
        struct iscsi_portal_group *tpg = container_of(se_tpg,           \
                        struct iscsi_portal_group, tpg_se_tpg);         \
        char *buf;                                                      \
@@ -1220,96 +1047,54 @@ static ssize_t iscsi_tpg_param_store_##name(                            \
 out:                                                                   \
        kfree(buf);                                                     \
        iscsit_put_tpg(tpg);                                            \
-       return -EINVAL;                                         \
-}
-
-#define TPG_PARAM_ATTR(_name, _mode) TF_TPG_PARAM_ATTR(iscsi, _name, _mode);
+       return -EINVAL;                                                 \
+}                                                                      \
+CONFIGFS_ATTR(iscsi_tpg_param_, name)
 
 DEF_TPG_PARAM(AuthMethod);
-TPG_PARAM_ATTR(AuthMethod, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(HeaderDigest);
-TPG_PARAM_ATTR(HeaderDigest, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(DataDigest);
-TPG_PARAM_ATTR(DataDigest, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(MaxConnections);
-TPG_PARAM_ATTR(MaxConnections, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(TargetAlias);
-TPG_PARAM_ATTR(TargetAlias, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(InitialR2T);
-TPG_PARAM_ATTR(InitialR2T, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(ImmediateData);
-TPG_PARAM_ATTR(ImmediateData, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(MaxRecvDataSegmentLength);
-TPG_PARAM_ATTR(MaxRecvDataSegmentLength, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(MaxXmitDataSegmentLength);
-TPG_PARAM_ATTR(MaxXmitDataSegmentLength, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(MaxBurstLength);
-TPG_PARAM_ATTR(MaxBurstLength, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(FirstBurstLength);
-TPG_PARAM_ATTR(FirstBurstLength, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(DefaultTime2Wait);
-TPG_PARAM_ATTR(DefaultTime2Wait, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(DefaultTime2Retain);
-TPG_PARAM_ATTR(DefaultTime2Retain, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(MaxOutstandingR2T);
-TPG_PARAM_ATTR(MaxOutstandingR2T, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(DataPDUInOrder);
-TPG_PARAM_ATTR(DataPDUInOrder, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(DataSequenceInOrder);
-TPG_PARAM_ATTR(DataSequenceInOrder, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(ErrorRecoveryLevel);
-TPG_PARAM_ATTR(ErrorRecoveryLevel, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(IFMarker);
-TPG_PARAM_ATTR(IFMarker, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(OFMarker);
-TPG_PARAM_ATTR(OFMarker, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(IFMarkInt);
-TPG_PARAM_ATTR(IFMarkInt, S_IRUGO | S_IWUSR);
-
 DEF_TPG_PARAM(OFMarkInt);
-TPG_PARAM_ATTR(OFMarkInt, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
-       &iscsi_tpg_param_AuthMethod.attr,
-       &iscsi_tpg_param_HeaderDigest.attr,
-       &iscsi_tpg_param_DataDigest.attr,
-       &iscsi_tpg_param_MaxConnections.attr,
-       &iscsi_tpg_param_TargetAlias.attr,
-       &iscsi_tpg_param_InitialR2T.attr,
-       &iscsi_tpg_param_ImmediateData.attr,
-       &iscsi_tpg_param_MaxRecvDataSegmentLength.attr,
-       &iscsi_tpg_param_MaxXmitDataSegmentLength.attr,
-       &iscsi_tpg_param_MaxBurstLength.attr,
-       &iscsi_tpg_param_FirstBurstLength.attr,
-       &iscsi_tpg_param_DefaultTime2Wait.attr,
-       &iscsi_tpg_param_DefaultTime2Retain.attr,
-       &iscsi_tpg_param_MaxOutstandingR2T.attr,
-       &iscsi_tpg_param_DataPDUInOrder.attr,
-       &iscsi_tpg_param_DataSequenceInOrder.attr,
-       &iscsi_tpg_param_ErrorRecoveryLevel.attr,
-       &iscsi_tpg_param_IFMarker.attr,
-       &iscsi_tpg_param_OFMarker.attr,
-       &iscsi_tpg_param_IFMarkInt.attr,
-       &iscsi_tpg_param_OFMarkInt.attr,
+       &iscsi_tpg_param_attr_AuthMethod,
+       &iscsi_tpg_param_attr_HeaderDigest,
+       &iscsi_tpg_param_attr_DataDigest,
+       &iscsi_tpg_param_attr_MaxConnections,
+       &iscsi_tpg_param_attr_TargetAlias,
+       &iscsi_tpg_param_attr_InitialR2T,
+       &iscsi_tpg_param_attr_ImmediateData,
+       &iscsi_tpg_param_attr_MaxRecvDataSegmentLength,
+       &iscsi_tpg_param_attr_MaxXmitDataSegmentLength,
+       &iscsi_tpg_param_attr_MaxBurstLength,
+       &iscsi_tpg_param_attr_FirstBurstLength,
+       &iscsi_tpg_param_attr_DefaultTime2Wait,
+       &iscsi_tpg_param_attr_DefaultTime2Retain,
+       &iscsi_tpg_param_attr_MaxOutstandingR2T,
+       &iscsi_tpg_param_attr_DataPDUInOrder,
+       &iscsi_tpg_param_attr_DataSequenceInOrder,
+       &iscsi_tpg_param_attr_ErrorRecoveryLevel,
+       &iscsi_tpg_param_attr_IFMarker,
+       &iscsi_tpg_param_attr_OFMarker,
+       &iscsi_tpg_param_attr_IFMarkInt,
+       &iscsi_tpg_param_attr_OFMarkInt,
        NULL,
 };
 
@@ -1317,10 +1102,9 @@ static struct configfs_attribute *lio_target_tpg_param_attrs[] = {
 
 /* Start items for lio_target_tpg_cit */
 
-static ssize_t lio_target_tpg_show_enable(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t lio_target_tpg_enable_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct iscsi_portal_group *tpg = container_of(se_tpg,
                        struct iscsi_portal_group, tpg_se_tpg);
        ssize_t len;
@@ -1333,11 +1117,10 @@ static ssize_t lio_target_tpg_show_enable(
        return len;
 }
 
-static ssize_t lio_target_tpg_store_enable(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t lio_target_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct iscsi_portal_group *tpg = container_of(se_tpg,
                        struct iscsi_portal_group, tpg_se_tpg);
        u32 op;
@@ -1375,20 +1158,19 @@ static ssize_t lio_target_tpg_store_enable(
        return -EINVAL;
 }
 
-TF_TPG_BASE_ATTR(lio_target, enable, S_IRUGO | S_IWUSR);
 
-static ssize_t lio_target_tpg_show_dynamic_sessions(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t lio_target_tpg_dynamic_sessions_show(struct config_item *item,
+               char *page)
 {
-       return target_show_dynamic_sessions(se_tpg, page);
+       return target_show_dynamic_sessions(to_tpg(item), page);
 }
 
-TF_TPG_BASE_ATTR_RO(lio_target, dynamic_sessions);
+CONFIGFS_ATTR(lio_target_tpg_, enable);
+CONFIGFS_ATTR_RO(lio_target_tpg_, dynamic_sessions);
 
 static struct configfs_attribute *lio_target_tpg_attrs[] = {
-       &lio_target_tpg_enable.attr,
-       &lio_target_tpg_dynamic_sessions.attr,
+       &lio_target_tpg_attr_enable,
+       &lio_target_tpg_attr_dynamic_sessions,
        NULL,
 };
 
@@ -1463,17 +1245,16 @@ static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg)
 
 /* Start LIO-Target TIQN struct contig_item lio_target_cit */
 
-static ssize_t lio_target_wwn_show_attr_lio_version(
-       struct target_fabric_configfs *tf,
-       char *page)
+static ssize_t lio_target_wwn_lio_version_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "Datera Inc. iSCSI Target "ISCSIT_VERSION"\n");
 }
 
-TF_WWN_ATTR_RO(lio_target, lio_version);
+CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version);
 
 static struct configfs_attribute *lio_target_wwn_attrs[] = {
-       &lio_target_wwn_lio_version.attr,
+       &lio_target_wwn_attr_lio_version,
        NULL,
 };
 
@@ -1552,77 +1333,47 @@ static void lio_target_call_coredeltiqn(
 
 #define DEF_DISC_AUTH_STR(name, flags)                                 \
        __DEF_NACL_AUTH_STR(disc, name, flags)                          \
-static ssize_t iscsi_disc_show_##name(                                 \
-       struct target_fabric_configfs *tf,                              \
-       char *page)                                                     \
+static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \
 {                                                                      \
-       return __iscsi_disc_show_##name(&iscsit_global->discovery_acl,  \
+       return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl,\
                page);                                                  \
 }                                                                      \
-static ssize_t iscsi_disc_store_##name(                                        \
-       struct target_fabric_configfs *tf,                              \
-       const char *page,                                               \
-       size_t count)                                                   \
+static ssize_t iscsi_disc_##name##_store(struct config_item *item,     \
+               const char *page, size_t count)                         \
 {                                                                      \
-       return __iscsi_disc_store_##name(&iscsit_global->discovery_acl, \
+       return __iscsi_disc_##name##_store(&iscsit_global->discovery_acl,       \
                page, count);                                           \
-}
+                                                                       \
+}                                                                      \
+CONFIGFS_ATTR(iscsi_disc_, name)
+
+DEF_DISC_AUTH_STR(userid, NAF_USERID_SET);
+DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET);
+DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
+DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
 
 #define DEF_DISC_AUTH_INT(name)                                                \
        __DEF_NACL_AUTH_INT(disc, name)                                 \
-static ssize_t iscsi_disc_show_##name(                                 \
-       struct target_fabric_configfs *tf,                              \
-       char *page)                                                     \
+static ssize_t iscsi_disc_##name##_show(struct config_item *item, char *page) \
 {                                                                      \
-       return __iscsi_disc_show_##name(&iscsit_global->discovery_acl,  \
+       return __iscsi_disc_##name##_show(&iscsit_global->discovery_acl, \
                        page);                                          \
-}
-
-#define DISC_AUTH_ATTR(_name, _mode) TF_DISC_ATTR(iscsi, _name, _mode)
-#define DISC_AUTH_ATTR_RO(_name) TF_DISC_ATTR_RO(iscsi, _name)
+}                                                                      \
+CONFIGFS_ATTR_RO(iscsi_disc_, name)
 
-/*
- * One-way authentication userid
- */
-DEF_DISC_AUTH_STR(userid, NAF_USERID_SET);
-DISC_AUTH_ATTR(userid, S_IRUGO | S_IWUSR);
-/*
- * One-way authentication password
- */
-DEF_DISC_AUTH_STR(password, NAF_PASSWORD_SET);
-DISC_AUTH_ATTR(password, S_IRUGO | S_IWUSR);
-/*
- * Enforce mutual authentication
- */
 DEF_DISC_AUTH_INT(authenticate_target);
-DISC_AUTH_ATTR_RO(authenticate_target);
-/*
- * Mutual authentication userid
- */
-DEF_DISC_AUTH_STR(userid_mutual, NAF_USERID_IN_SET);
-DISC_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR);
-/*
- * Mutual authentication password
- */
-DEF_DISC_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET);
-DISC_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR);
 
-/*
- * enforce_discovery_auth
- */
-static ssize_t iscsi_disc_show_enforce_discovery_auth(
-       struct target_fabric_configfs *tf,
-       char *page)
+
+static ssize_t iscsi_disc_enforce_discovery_auth_show(struct config_item *item,
+               char *page)
 {
        struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth;
 
        return sprintf(page, "%d\n", discovery_auth->enforce_discovery_auth);
 }
 
-static ssize_t iscsi_disc_store_enforce_discovery_auth(
-       struct target_fabric_configfs *tf,
-       const char *page,
-       size_t count)
+static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
+               const char *page, size_t count)
 {
        struct iscsi_param *param;
        struct iscsi_portal_group *discovery_tpg = iscsit_global->discovery_tpg;
@@ -1677,15 +1428,15 @@ static ssize_t iscsi_disc_store_enforce_discovery_auth(
        return count;
 }
 
-DISC_AUTH_ATTR(enforce_discovery_auth, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth);
 
 static struct configfs_attribute *lio_target_discovery_auth_attrs[] = {
-       &iscsi_disc_userid.attr,
-       &iscsi_disc_password.attr,
-       &iscsi_disc_authenticate_target.attr,
-       &iscsi_disc_userid_mutual.attr,
-       &iscsi_disc_password_mutual.attr,
-       &iscsi_disc_enforce_discovery_auth.attr,
+       &iscsi_disc_attr_userid,
+       &iscsi_disc_attr_password,
+       &iscsi_disc_attr_authenticate_target,
+       &iscsi_disc_attr_userid_mutual,
+       &iscsi_disc_attr_password_mutual,
+       &iscsi_disc_attr_enforce_discovery_auth,
        NULL,
 };
 
index 9dd94ff0b62c0e53e39dbd3685ce1e3dc272cb1b..411cb266a47d5c39bd7df5ec4b705bce68ef0ca2 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/export.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
-#include <target/configfs_macros.h>
 
 #include <target/iscsi/iscsi_target_core.h>
 #include "iscsi_target_parameters.h"
 /*
  * Instance Attributes Table
  */
-CONFIGFS_EATTR_STRUCT(iscsi_stat_instance, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_INSTANCE_ATTR(_name, _mode)                 \
-static struct iscsi_stat_instance_attribute                    \
-                       iscsi_stat_instance_##_name =           \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_instance_show_attr_##_name,                  \
-       iscsi_stat_instance_store_attr_##_name);
-
-#define ISCSI_STAT_INSTANCE_ATTR_RO(_name)                     \
-static struct iscsi_stat_instance_attribute                    \
-                       iscsi_stat_instance_##_name =           \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_instance_show_attr_##_name);
-
-static ssize_t iscsi_stat_instance_show_attr_inst(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
-{
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_instance_tiqn(struct config_item *item)
+{
+       struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_wwn_stat_grps, iscsi_instance_group);
+       return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
 
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_instance_inst_show(struct config_item *item,
+               char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%u\n",
+                       iscsi_instance_tiqn(item)->tiqn_index);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(inst);
 
-static ssize_t iscsi_stat_instance_show_attr_min_ver(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_min_ver_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(min_ver);
 
-static ssize_t iscsi_stat_instance_show_attr_max_ver(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_max_ver_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DRAFT20_VERSION);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(max_ver);
 
-static ssize_t iscsi_stat_instance_show_attr_portals(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_portals_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_num_tpg_nps);
+       return snprintf(page, PAGE_SIZE, "%u\n",
+                       iscsi_instance_tiqn(item)->tiqn_num_tpg_nps);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(portals);
 
-static ssize_t iscsi_stat_instance_show_attr_nodes(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_nodes_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_INST_NUM_NODES);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(nodes);
 
-static ssize_t iscsi_stat_instance_show_attr_sessions(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_sessions_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_nsessions);
+       return snprintf(page, PAGE_SIZE, "%u\n",
+               iscsi_instance_tiqn(item)->tiqn_nsessions);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(sessions);
 
-static ssize_t iscsi_stat_instance_show_attr_fail_sess(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_sess_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
        u32 sess_err_count;
 
@@ -131,88 +110,84 @@ static ssize_t iscsi_stat_instance_show_attr_fail_sess(
 
        return snprintf(page, PAGE_SIZE, "%u\n", sess_err_count);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_sess);
 
-static ssize_t iscsi_stat_instance_show_attr_fail_type(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_type_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n",
                        sess_err->last_sess_failure_type);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_type);
 
-static ssize_t iscsi_stat_instance_show_attr_fail_rem_name(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_fail_rem_name_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_instance_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
 
        return snprintf(page, PAGE_SIZE, "%s\n",
                        sess_err->last_sess_fail_rem_name[0] ?
                        sess_err->last_sess_fail_rem_name : NONE);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(fail_rem_name);
 
-static ssize_t iscsi_stat_instance_show_attr_disc_time(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_disc_time_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_DISCONTINUITY_TIME);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(disc_time);
 
-static ssize_t iscsi_stat_instance_show_attr_description(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_description_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%s\n", ISCSI_INST_DESCR);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(description);
 
-static ssize_t iscsi_stat_instance_show_attr_vendor(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_vendor_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "Datera, Inc. iSCSI-Target\n");
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(vendor);
 
-static ssize_t iscsi_stat_instance_show_attr_version(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_instance_version_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%s\n", ISCSIT_VERSION);
 }
-ISCSI_STAT_INSTANCE_ATTR_RO(version);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_instance, iscsi_wwn_stat_grps,
-               iscsi_instance_group);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, min_ver);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, max_ver);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, portals);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, nodes);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, sessions);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_sess);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_type);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, fail_rem_name);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, disc_time);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, description);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, vendor);
+CONFIGFS_ATTR_RO(iscsi_stat_instance_, version);
 
 static struct configfs_attribute *iscsi_stat_instance_attrs[] = {
-       &iscsi_stat_instance_inst.attr,
-       &iscsi_stat_instance_min_ver.attr,
-       &iscsi_stat_instance_max_ver.attr,
-       &iscsi_stat_instance_portals.attr,
-       &iscsi_stat_instance_nodes.attr,
-       &iscsi_stat_instance_sessions.attr,
-       &iscsi_stat_instance_fail_sess.attr,
-       &iscsi_stat_instance_fail_type.attr,
-       &iscsi_stat_instance_fail_rem_name.attr,
-       &iscsi_stat_instance_disc_time.attr,
-       &iscsi_stat_instance_description.attr,
-       &iscsi_stat_instance_vendor.attr,
-       &iscsi_stat_instance_version.attr,
+       &iscsi_stat_instance_attr_inst,
+       &iscsi_stat_instance_attr_min_ver,
+       &iscsi_stat_instance_attr_max_ver,
+       &iscsi_stat_instance_attr_portals,
+       &iscsi_stat_instance_attr_nodes,
+       &iscsi_stat_instance_attr_sessions,
+       &iscsi_stat_instance_attr_fail_sess,
+       &iscsi_stat_instance_attr_fail_type,
+       &iscsi_stat_instance_attr_fail_rem_name,
+       &iscsi_stat_instance_attr_disc_time,
+       &iscsi_stat_instance_attr_description,
+       &iscsi_stat_instance_attr_vendor,
+       &iscsi_stat_instance_attr_version,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_instance_item_ops = {
-       .show_attribute         = iscsi_stat_instance_attr_show,
-       .store_attribute        = iscsi_stat_instance_attr_store,
-};
-
 struct config_item_type iscsi_stat_instance_cit = {
-       .ct_item_ops            = &iscsi_stat_instance_item_ops,
        .ct_attrs               = iscsi_stat_instance_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -220,81 +195,61 @@ struct config_item_type iscsi_stat_instance_cit = {
 /*
  * Instance Session Failure Stats Table
  */
-CONFIGFS_EATTR_STRUCT(iscsi_stat_sess_err, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_SESS_ERR_ATTR(_name, _mode)                 \
-static struct iscsi_stat_sess_err_attribute                    \
-                       iscsi_stat_sess_err_##_name =           \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_sess_err_show_attr_##_name,                  \
-       iscsi_stat_sess_err_store_attr_##_name);
-
-#define ISCSI_STAT_SESS_ERR_ATTR_RO(_name)                     \
-static struct iscsi_stat_sess_err_attribute                    \
-                       iscsi_stat_sess_err_##_name =           \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_sess_err_show_attr_##_name);
-
-static ssize_t iscsi_stat_sess_err_show_attr_inst(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
-{
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_sess_err_tiqn(struct config_item *item)
+{
+       struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_wwn_stat_grps, iscsi_sess_err_group);
+       return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
 
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_sess_err_inst_show(struct config_item *item,
+               char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%u\n",
+               iscsi_sess_err_tiqn(item)->tiqn_index);
 }
-ISCSI_STAT_SESS_ERR_ATTR_RO(inst);
 
-static ssize_t iscsi_stat_sess_err_show_attr_digest_errors(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_digest_errors_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n", sess_err->digest_errors);
 }
-ISCSI_STAT_SESS_ERR_ATTR_RO(digest_errors);
 
-static ssize_t iscsi_stat_sess_err_show_attr_cxn_errors(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_cxn_errors_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n", sess_err->cxn_timeout_errors);
 }
-ISCSI_STAT_SESS_ERR_ATTR_RO(cxn_errors);
 
-static ssize_t iscsi_stat_sess_err_show_attr_format_errors(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_err_format_errors_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_sess_err_tiqn(item);
        struct iscsi_sess_err_stats *sess_err = &tiqn->sess_err_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n", sess_err->pdu_format_errors);
 }
-ISCSI_STAT_SESS_ERR_ATTR_RO(format_errors);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_sess_err, iscsi_wwn_stat_grps,
-               iscsi_sess_err_group);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, digest_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, cxn_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_err_, format_errors);
 
 static struct configfs_attribute *iscsi_stat_sess_err_attrs[] = {
-       &iscsi_stat_sess_err_inst.attr,
-       &iscsi_stat_sess_err_digest_errors.attr,
-       &iscsi_stat_sess_err_cxn_errors.attr,
-       &iscsi_stat_sess_err_format_errors.attr,
+       &iscsi_stat_sess_err_attr_inst,
+       &iscsi_stat_sess_err_attr_digest_errors,
+       &iscsi_stat_sess_err_attr_cxn_errors,
+       &iscsi_stat_sess_err_attr_format_errors,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_sess_err_item_ops = {
-       .show_attribute         = iscsi_stat_sess_err_attr_show,
-       .store_attribute        = iscsi_stat_sess_err_attr_store,
-};
-
 struct config_item_type iscsi_stat_sess_err_cit = {
-       .ct_item_ops            = &iscsi_stat_sess_err_item_ops,
        .ct_attrs               = iscsi_stat_sess_err_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -302,42 +257,30 @@ struct config_item_type iscsi_stat_sess_err_cit = {
 /*
  * Target Attributes Table
  */
-CONFIGFS_EATTR_STRUCT(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_TGT_ATTR(_name, _mode)                      \
-static struct iscsi_stat_tgt_attr_attribute                    \
-                       iscsi_stat_tgt_attr_##_name =           \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_tgt-attr_show_attr_##_name,                  \
-       iscsi_stat_tgt_attr_store_attr_##_name);
-
-#define ISCSI_STAT_TGT_ATTR_RO(_name)                          \
-static struct iscsi_stat_tgt_attr_attribute                    \
-                       iscsi_stat_tgt_attr_##_name =           \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_tgt_attr_show_attr_##_name);
-
-static ssize_t iscsi_stat_tgt_attr_show_attr_inst(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
-{
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_tgt_attr_tiqn(struct config_item *item)
+{
+       struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_wwn_stat_grps, iscsi_tgt_attr_group);
+       return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
 
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_tgt_attr_inst_show(struct config_item *item,
+               char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%u\n",
+                       iscsi_tgt_attr_tiqn(item)->tiqn_index);
 }
-ISCSI_STAT_TGT_ATTR_RO(inst);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_indx(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_indx_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
 }
-ISCSI_STAT_TGT_ATTR_RO(indx);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_login_fails(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_login_fails_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        u32 fail_count;
 
@@ -349,13 +292,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_login_fails(
 
        return snprintf(page, PAGE_SIZE, "%u\n", fail_count);
 }
-ISCSI_STAT_TGT_ATTR_RO(login_fails);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_time(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_last_fail_time_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        u32 last_fail_time;
 
@@ -367,13 +308,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_time(
 
        return snprintf(page, PAGE_SIZE, "%u\n", last_fail_time);
 }
-ISCSI_STAT_TGT_ATTR_RO(last_fail_time);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_type(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_last_fail_type_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        u32 last_fail_type;
 
@@ -383,13 +322,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_last_fail_type(
 
        return snprintf(page, PAGE_SIZE, "%u\n", last_fail_type);
 }
-ISCSI_STAT_TGT_ATTR_RO(last_fail_type);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_name(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_name_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        unsigned char buf[224];
 
@@ -400,13 +337,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_name(
 
        return snprintf(page, PAGE_SIZE, "%s\n", buf);
 }
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_name);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_type_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                       struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        int ret;
 
@@ -419,13 +354,11 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr_type(
 
        return ret;
 }
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr_type);
 
-static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_tgt_attr_fail_intr_addr_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                       struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_tgt_attr_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        int ret;
 
@@ -435,30 +368,29 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
 
        return ret;
 }
-ISCSI_STAT_TGT_ATTR_RO(fail_intr_addr);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_tgt_attr, iscsi_wwn_stat_grps,
-               iscsi_tgt_attr_group);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, login_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_time);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, last_fail_type);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_name);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr_type);
+CONFIGFS_ATTR_RO(iscsi_stat_tgt_attr_, fail_intr_addr);
 
 static struct configfs_attribute *iscsi_stat_tgt_attr_attrs[] = {
-       &iscsi_stat_tgt_attr_inst.attr,
-       &iscsi_stat_tgt_attr_indx.attr,
-       &iscsi_stat_tgt_attr_login_fails.attr,
-       &iscsi_stat_tgt_attr_last_fail_time.attr,
-       &iscsi_stat_tgt_attr_last_fail_type.attr,
-       &iscsi_stat_tgt_attr_fail_intr_name.attr,
-       &iscsi_stat_tgt_attr_fail_intr_addr_type.attr,
-       &iscsi_stat_tgt_attr_fail_intr_addr.attr,
+       &iscsi_stat_tgt_attr_attr_inst,
+       &iscsi_stat_tgt_attr_attr_indx,
+       &iscsi_stat_tgt_attr_attr_login_fails,
+       &iscsi_stat_tgt_attr_attr_last_fail_time,
+       &iscsi_stat_tgt_attr_attr_last_fail_type,
+       &iscsi_stat_tgt_attr_attr_fail_intr_name,
+       &iscsi_stat_tgt_attr_attr_fail_intr_addr_type,
+       &iscsi_stat_tgt_attr_attr_fail_intr_addr,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_tgt_attr_item_ops = {
-       .show_attribute         = iscsi_stat_tgt_attr_attr_show,
-       .store_attribute        = iscsi_stat_tgt_attr_attr_store,
-};
-
 struct config_item_type iscsi_stat_tgt_attr_cit = {
-       .ct_item_ops            = &iscsi_stat_tgt_attr_item_ops,
        .ct_attrs               = iscsi_stat_tgt_attr_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -466,42 +398,29 @@ struct config_item_type iscsi_stat_tgt_attr_cit = {
 /*
  * Target Login Stats Table
  */
-CONFIGFS_EATTR_STRUCT(iscsi_stat_login, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_LOGIN(_name, _mode)                         \
-static struct iscsi_stat_login_attribute                       \
-                       iscsi_stat_login_##_name =              \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_login_show_attr_##_name,                     \
-       iscsi_stat_login_store_attr_##_name);
-
-#define ISCSI_STAT_LOGIN_RO(_name)                             \
-static struct iscsi_stat_login_attribute                       \
-                       iscsi_stat_login_##_name =              \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_login_show_attr_##_name);
-
-static ssize_t iscsi_stat_login_show_attr_inst(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
-{
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+static struct iscsi_tiqn *iscsi_login_stat_tiqn(struct config_item *item)
+{
+       struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_wwn_stat_grps, iscsi_login_stats_group);
+       return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
 
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_login_inst_show(struct config_item *item, char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%u\n",
+               iscsi_login_stat_tiqn(item)->tiqn_index);
 }
-ISCSI_STAT_LOGIN_RO(inst);
 
-static ssize_t iscsi_stat_login_show_attr_indx(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_indx_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
 }
-ISCSI_STAT_LOGIN_RO(indx);
 
-static ssize_t iscsi_stat_login_show_attr_accepts(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_accepts_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -511,13 +430,11 @@ static ssize_t iscsi_stat_login_show_attr_accepts(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(accepts);
 
-static ssize_t iscsi_stat_login_show_attr_other_fails(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_other_fails_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -527,13 +444,11 @@ static ssize_t iscsi_stat_login_show_attr_other_fails(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(other_fails);
 
-static ssize_t iscsi_stat_login_show_attr_redirects(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_redirects_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -543,13 +458,11 @@ static ssize_t iscsi_stat_login_show_attr_redirects(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(redirects);
 
-static ssize_t iscsi_stat_login_show_attr_authorize_fails(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_authorize_fails_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -559,13 +472,11 @@ static ssize_t iscsi_stat_login_show_attr_authorize_fails(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(authorize_fails);
 
-static ssize_t iscsi_stat_login_show_attr_authenticate_fails(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_authenticate_fails_show(
+               struct config_item *item, char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -575,13 +486,11 @@ static ssize_t iscsi_stat_login_show_attr_authenticate_fails(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(authenticate_fails);
 
-static ssize_t iscsi_stat_login_show_attr_negotiate_fails(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_login_negotiate_fails_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                               struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_login_stat_tiqn(item);
        struct iscsi_login_stats *lstat = &tiqn->login_stats;
        ssize_t ret;
 
@@ -591,30 +500,29 @@ static ssize_t iscsi_stat_login_show_attr_negotiate_fails(
 
        return ret;
 }
-ISCSI_STAT_LOGIN_RO(negotiate_fails);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_login, iscsi_wwn_stat_grps,
-               iscsi_login_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, accepts);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, other_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, redirects);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, authorize_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, authenticate_fails);
+CONFIGFS_ATTR_RO(iscsi_stat_login_, negotiate_fails);
 
 static struct configfs_attribute *iscsi_stat_login_stats_attrs[] = {
-       &iscsi_stat_login_inst.attr,
-       &iscsi_stat_login_indx.attr,
-       &iscsi_stat_login_accepts.attr,
-       &iscsi_stat_login_other_fails.attr,
-       &iscsi_stat_login_redirects.attr,
-       &iscsi_stat_login_authorize_fails.attr,
-       &iscsi_stat_login_authenticate_fails.attr,
-       &iscsi_stat_login_negotiate_fails.attr,
+       &iscsi_stat_login_attr_inst,
+       &iscsi_stat_login_attr_indx,
+       &iscsi_stat_login_attr_accepts,
+       &iscsi_stat_login_attr_other_fails,
+       &iscsi_stat_login_attr_redirects,
+       &iscsi_stat_login_attr_authorize_fails,
+       &iscsi_stat_login_attr_authenticate_fails,
+       &iscsi_stat_login_attr_negotiate_fails,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_login_stats_item_ops = {
-       .show_attribute         = iscsi_stat_login_attr_show,
-       .store_attribute        = iscsi_stat_login_attr_store,
-};
-
 struct config_item_type iscsi_stat_login_cit = {
-       .ct_item_ops            = &iscsi_stat_login_stats_item_ops,
        .ct_attrs               = iscsi_stat_login_stats_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -622,78 +530,56 @@ struct config_item_type iscsi_stat_login_cit = {
 /*
  * Target Logout Stats Table
  */
-
-CONFIGFS_EATTR_STRUCT(iscsi_stat_logout, iscsi_wwn_stat_grps);
-#define ISCSI_STAT_LOGOUT(_name, _mode)                                \
-static struct iscsi_stat_logout_attribute                      \
-                       iscsi_stat_logout_##_name =             \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_logout_show_attr_##_name,                    \
-       iscsi_stat_logout_store_attr_##_name);
-
-#define ISCSI_STAT_LOGOUT_RO(_name)                            \
-static struct iscsi_stat_logout_attribute                      \
-                       iscsi_stat_logout_##_name =             \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_logout_show_attr_##_name);
-
-static ssize_t iscsi_stat_logout_show_attr_inst(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static struct iscsi_tiqn *iscsi_logout_stat_tiqn(struct config_item *item)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                       struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_wwn_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_wwn_stat_grps, iscsi_logout_stats_group);
+       return container_of(igrps, struct iscsi_tiqn, tiqn_stat_grps);
+}
 
-       return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
+static ssize_t iscsi_stat_logout_inst_show(struct config_item *item, char *page)
+{
+       return snprintf(page, PAGE_SIZE, "%u\n",
+               iscsi_logout_stat_tiqn(item)->tiqn_index);
 }
-ISCSI_STAT_LOGOUT_RO(inst);
 
-static ssize_t iscsi_stat_logout_show_attr_indx(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_indx_show(struct config_item *item, char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", ISCSI_NODE_INDEX);
 }
-ISCSI_STAT_LOGOUT_RO(indx);
 
-static ssize_t iscsi_stat_logout_show_attr_normal_logouts(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_normal_logouts_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                       struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
        struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n", lstats->normal_logouts);
 }
-ISCSI_STAT_LOGOUT_RO(normal_logouts);
 
-static ssize_t iscsi_stat_logout_show_attr_abnormal_logouts(
-       struct iscsi_wwn_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_logout_abnormal_logouts_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_tiqn *tiqn = container_of(igrps,
-                       struct iscsi_tiqn, tiqn_stat_grps);
+       struct iscsi_tiqn *tiqn = iscsi_logout_stat_tiqn(item);
        struct iscsi_logout_stats *lstats = &tiqn->logout_stats;
 
        return snprintf(page, PAGE_SIZE, "%u\n", lstats->abnormal_logouts);
 }
-ISCSI_STAT_LOGOUT_RO(abnormal_logouts);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_logout, iscsi_wwn_stat_grps,
-               iscsi_logout_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, normal_logouts);
+CONFIGFS_ATTR_RO(iscsi_stat_logout_, abnormal_logouts);
 
 static struct configfs_attribute *iscsi_stat_logout_stats_attrs[] = {
-       &iscsi_stat_logout_inst.attr,
-       &iscsi_stat_logout_indx.attr,
-       &iscsi_stat_logout_normal_logouts.attr,
-       &iscsi_stat_logout_abnormal_logouts.attr,
+       &iscsi_stat_logout_attr_inst,
+       &iscsi_stat_logout_attr_indx,
+       &iscsi_stat_logout_attr_normal_logouts,
+       &iscsi_stat_logout_attr_abnormal_logouts,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_logout_stats_item_ops = {
-       .show_attribute         = iscsi_stat_logout_attr_show,
-       .store_attribute        = iscsi_stat_logout_attr_store,
-};
-
 struct config_item_type iscsi_stat_logout_cit = {
-       .ct_item_ops            = &iscsi_stat_logout_stats_item_ops,
        .ct_attrs               = iscsi_stat_logout_stats_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -701,39 +587,26 @@ struct config_item_type iscsi_stat_logout_cit = {
 /*
  * Session Stats Table
  */
+static struct iscsi_node_acl *iscsi_stat_nacl(struct config_item *item)
+{
+       struct iscsi_node_stat_grps *igrps = container_of(to_config_group(item),
+                       struct iscsi_node_stat_grps, iscsi_sess_stats_group);
+       return container_of(igrps, struct iscsi_node_acl, node_stat_grps);
+}
 
-CONFIGFS_EATTR_STRUCT(iscsi_stat_sess, iscsi_node_stat_grps);
-#define ISCSI_STAT_SESS(_name, _mode)                          \
-static struct iscsi_stat_sess_attribute                                \
-                       iscsi_stat_sess_##_name =               \
-       __CONFIGFS_EATTR(_name, _mode,                          \
-       iscsi_stat_sess_show_attr_##_name,                      \
-       iscsi_stat_sess_store_attr_##_name);
-
-#define ISCSI_STAT_SESS_RO(_name)                              \
-static struct iscsi_stat_sess_attribute                                \
-                       iscsi_stat_sess_##_name =               \
-       __CONFIGFS_EATTR_RO(_name,                              \
-       iscsi_stat_sess_show_attr_##_name);
-
-static ssize_t iscsi_stat_sess_show_attr_inst(
-       struct iscsi_node_stat_grps *igrps, char *page)
-{
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+static ssize_t iscsi_stat_sess_inst_show(struct config_item *item, char *page)
+{
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_wwn *wwn = acl->se_node_acl.se_tpg->se_tpg_wwn;
        struct iscsi_tiqn *tiqn = container_of(wwn,
                        struct iscsi_tiqn, tiqn_wwn);
 
        return snprintf(page, PAGE_SIZE, "%u\n", tiqn->tiqn_index);
 }
-ISCSI_STAT_SESS_RO(inst);
 
-static ssize_t iscsi_stat_sess_show_attr_node(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_node_show(struct config_item *item, char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -751,13 +624,10 @@ static ssize_t iscsi_stat_sess_show_attr_node(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(node);
 
-static ssize_t iscsi_stat_sess_show_attr_indx(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_indx_show(struct config_item *item, char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -775,13 +645,11 @@ static ssize_t iscsi_stat_sess_show_attr_indx(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(indx);
 
-static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_cmd_pdus_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -799,13 +667,11 @@ static ssize_t iscsi_stat_sess_show_attr_cmd_pdus(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(cmd_pdus);
 
-static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_rsp_pdus_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -823,13 +689,11 @@ static ssize_t iscsi_stat_sess_show_attr_rsp_pdus(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(rsp_pdus);
 
-static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_txdata_octs_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -847,13 +711,11 @@ static ssize_t iscsi_stat_sess_show_attr_txdata_octs(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(txdata_octs);
 
-static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_rxdata_octs_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -871,13 +733,11 @@ static ssize_t iscsi_stat_sess_show_attr_rxdata_octs(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(rxdata_octs);
 
-static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_conn_digest_errors_show(struct config_item *item,
+               char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -895,13 +755,11 @@ static ssize_t iscsi_stat_sess_show_attr_conn_digest_errors(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(conn_digest_errors);
 
-static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
-       struct iscsi_node_stat_grps *igrps, char *page)
+static ssize_t iscsi_stat_sess_conn_timeout_errors_show(
+               struct config_item *item, char *page)
 {
-       struct iscsi_node_acl *acl = container_of(igrps,
-                       struct iscsi_node_acl, node_stat_grps);
+       struct iscsi_node_acl *acl = iscsi_stat_nacl(item);
        struct se_node_acl *se_nacl = &acl->se_node_acl;
        struct iscsi_session *sess;
        struct se_session *se_sess;
@@ -919,31 +777,31 @@ static ssize_t iscsi_stat_sess_show_attr_conn_timeout_errors(
 
        return ret;
 }
-ISCSI_STAT_SESS_RO(conn_timeout_errors);
 
-CONFIGFS_EATTR_OPS(iscsi_stat_sess, iscsi_node_stat_grps,
-               iscsi_sess_stats_group);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, inst);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, node);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, indx);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, cmd_pdus);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, rsp_pdus);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, txdata_octs);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, rxdata_octs);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_digest_errors);
+CONFIGFS_ATTR_RO(iscsi_stat_sess_, conn_timeout_errors);
 
 static struct configfs_attribute *iscsi_stat_sess_stats_attrs[] = {
-       &iscsi_stat_sess_inst.attr,
-       &iscsi_stat_sess_node.attr,
-       &iscsi_stat_sess_indx.attr,
-       &iscsi_stat_sess_cmd_pdus.attr,
-       &iscsi_stat_sess_rsp_pdus.attr,
-       &iscsi_stat_sess_txdata_octs.attr,
-       &iscsi_stat_sess_rxdata_octs.attr,
-       &iscsi_stat_sess_conn_digest_errors.attr,
-       &iscsi_stat_sess_conn_timeout_errors.attr,
+       &iscsi_stat_sess_attr_inst,
+       &iscsi_stat_sess_attr_node,
+       &iscsi_stat_sess_attr_indx,
+       &iscsi_stat_sess_attr_cmd_pdus,
+       &iscsi_stat_sess_attr_rsp_pdus,
+       &iscsi_stat_sess_attr_txdata_octs,
+       &iscsi_stat_sess_attr_rxdata_octs,
+       &iscsi_stat_sess_attr_conn_digest_errors,
+       &iscsi_stat_sess_attr_conn_timeout_errors,
        NULL,
 };
 
-static struct configfs_item_operations iscsi_stat_sess_stats_item_ops = {
-       .show_attribute         = iscsi_stat_sess_attr_show,
-       .store_attribute        = iscsi_stat_sess_attr_store,
-};
-
 struct config_item_type iscsi_stat_sess_cit = {
-       .ct_item_ops            = &iscsi_stat_sess_stats_item_ops,
        .ct_attrs               = iscsi_stat_sess_stats_attrs,
        .ct_owner               = THIS_MODULE,
 };
index 5bc85ffed7204f21871a31d7346b93885b437cf8..4fb0eca86857e2f3229603397138d4c793b57eff 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
 
 #include "tcm_loop.h"
 
@@ -377,7 +376,6 @@ static struct scsi_host_template tcm_loop_driver_template = {
        .use_clustering         = DISABLE_CLUSTERING,
        .slave_alloc            = tcm_loop_slave_alloc,
        .module                 = THIS_MODULE,
-       .use_blk_tags           = 1,
        .track_queue_depth      = 1,
 };
 
@@ -763,21 +761,20 @@ static void tcm_loop_port_unlink(
 
 /* End items for tcm_loop_port_cit */
 
-static ssize_t tcm_loop_tpg_attrib_show_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_loop_tpg_attrib_fabric_prot_type_show(
+               struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
                                                   tl_se_tpg);
 
        return sprintf(page, "%d\n", tl_tpg->tl_fabric_prot_type);
 }
 
-static ssize_t tcm_loop_tpg_attrib_store_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_loop_tpg_attrib_fabric_prot_type_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
                                                   tl_se_tpg);
        unsigned long val;
@@ -796,10 +793,10 @@ static ssize_t tcm_loop_tpg_attrib_store_fabric_prot_type(
        return count;
 }
 
-TF_TPG_ATTRIB_ATTR(tcm_loop, fabric_prot_type, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_loop_tpg_attrib_, fabric_prot_type);
 
 static struct configfs_attribute *tcm_loop_tpg_attrib_attrs[] = {
-       &tcm_loop_tpg_attrib_fabric_prot_type.attr,
+       &tcm_loop_tpg_attrib_attr_fabric_prot_type,
        NULL,
 };
 
@@ -894,10 +891,9 @@ static int tcm_loop_drop_nexus(
 
 /* End items for tcm_loop_nexus_cit */
 
-static ssize_t tcm_loop_tpg_show_nexus(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_loop_tpg_nexus_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
                        struct tcm_loop_tpg, tl_se_tpg);
        struct tcm_loop_nexus *tl_nexus;
@@ -913,11 +909,10 @@ static ssize_t tcm_loop_tpg_show_nexus(
        return ret;
 }
 
-static ssize_t tcm_loop_tpg_store_nexus(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_loop_tpg_nexus_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
                        struct tcm_loop_tpg, tl_se_tpg);
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
@@ -992,12 +987,10 @@ static ssize_t tcm_loop_tpg_store_nexus(
        return count;
 }
 
-TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
-
-static ssize_t tcm_loop_tpg_show_transport_status(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t tcm_loop_tpg_transport_status_show(struct config_item *item,
+               char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
                        struct tcm_loop_tpg, tl_se_tpg);
        const char *status = NULL;
@@ -1020,11 +1013,10 @@ static ssize_t tcm_loop_tpg_show_transport_status(
        return ret;
 }
 
-static ssize_t tcm_loop_tpg_store_transport_status(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t tcm_loop_tpg_transport_status_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
                        struct tcm_loop_tpg, tl_se_tpg);
 
@@ -1044,11 +1036,12 @@ static ssize_t tcm_loop_tpg_store_transport_status(
        return -EINVAL;
 }
 
-TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(tcm_loop_tpg_, nexus);
+CONFIGFS_ATTR(tcm_loop_tpg_, transport_status);
 
 static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
-       &tcm_loop_tpg_nexus.attr,
-       &tcm_loop_tpg_transport_status.attr,
+       &tcm_loop_tpg_attr_nexus,
+       &tcm_loop_tpg_attr_transport_status,
        NULL,
 };
 
@@ -1216,17 +1209,15 @@ static void tcm_loop_drop_scsi_hba(
 }
 
 /* Start items for tcm_loop_cit */
-static ssize_t tcm_loop_wwn_show_attr_version(
-       struct target_fabric_configfs *tf,
-       char *page)
+static ssize_t tcm_loop_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "TCM Loopback Fabric module %s\n", TCM_LOOP_VERSION);
 }
 
-TF_WWN_ATTR_RO(tcm_loop, version);
+CONFIGFS_ATTR_RO(tcm_loop_wwn_, version);
 
 static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
-       &tcm_loop_wwn_version.attr,
+       &tcm_loop_wwn_attr_version,
        NULL,
 };
 
index 0edf320fb68547a4f4c6d0b8d46687727d47c557..35f7d31b29d2eb05c13985e4ab45df0df41669e6 100644 (file)
@@ -35,8 +35,6 @@
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 #include <asm/unaligned.h>
 
 #include "sbp_target.h"
@@ -2111,24 +2109,21 @@ static void sbp_drop_tport(struct se_wwn *wwn)
        kfree(tport);
 }
 
-static ssize_t sbp_wwn_show_attr_version(
-               struct target_fabric_configfs *tf,
-               char *page)
+static ssize_t sbp_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "FireWire SBP fabric module %s\n", SBP_VERSION);
 }
 
-TF_WWN_ATTR_RO(sbp, version);
+CONFIGFS_ATTR_RO(sbp_wwn_, version);
 
 static struct configfs_attribute *sbp_wwn_attrs[] = {
-       &sbp_wwn_version.attr,
+       &sbp_wwn_attr_version,
        NULL,
 };
 
-static ssize_t sbp_tpg_show_directory_id(
-               struct se_portal_group *se_tpg,
-               char *page)
+static ssize_t sbp_tpg_directory_id_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
 
@@ -2138,11 +2133,10 @@ static ssize_t sbp_tpg_show_directory_id(
                return sprintf(page, "%06x\n", tport->directory_id);
 }
 
-static ssize_t sbp_tpg_store_directory_id(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t sbp_tpg_directory_id_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        unsigned long val;
@@ -2166,20 +2160,18 @@ static ssize_t sbp_tpg_store_directory_id(
        return count;
 }
 
-static ssize_t sbp_tpg_show_enable(
-               struct se_portal_group *se_tpg,
-               char *page)
+static ssize_t sbp_tpg_enable_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        return sprintf(page, "%d\n", tport->enable);
 }
 
-static ssize_t sbp_tpg_store_enable(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t sbp_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        unsigned long val;
@@ -2219,29 +2211,28 @@ static ssize_t sbp_tpg_store_enable(
        return count;
 }
 
-TF_TPG_BASE_ATTR(sbp, directory_id, S_IRUGO | S_IWUSR);
-TF_TPG_BASE_ATTR(sbp, enable, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(sbp_tpg_, directory_id);
+CONFIGFS_ATTR(sbp_tpg_, enable);
 
 static struct configfs_attribute *sbp_tpg_base_attrs[] = {
-       &sbp_tpg_directory_id.attr,
-       &sbp_tpg_enable.attr,
+       &sbp_tpg_attr_directory_id,
+       &sbp_tpg_attr_enable,
        NULL,
 };
 
-static ssize_t sbp_tpg_attrib_show_mgt_orb_timeout(
-               struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_mgt_orb_timeout_show(struct config_item *item,
                char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        return sprintf(page, "%d\n", tport->mgt_orb_timeout);
 }
 
-static ssize_t sbp_tpg_attrib_store_mgt_orb_timeout(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t sbp_tpg_attrib_mgt_orb_timeout_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        unsigned long val;
@@ -2264,20 +2255,19 @@ static ssize_t sbp_tpg_attrib_store_mgt_orb_timeout(
        return count;
 }
 
-static ssize_t sbp_tpg_attrib_show_max_reconnect_timeout(
-               struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_max_reconnect_timeout_show(struct config_item *item,
                char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        return sprintf(page, "%d\n", tport->max_reconnect_timeout);
 }
 
-static ssize_t sbp_tpg_attrib_store_max_reconnect_timeout(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t sbp_tpg_attrib_max_reconnect_timeout_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        unsigned long val;
@@ -2300,20 +2290,19 @@ static ssize_t sbp_tpg_attrib_store_max_reconnect_timeout(
        return count;
 }
 
-static ssize_t sbp_tpg_attrib_show_max_logins_per_lun(
-               struct se_portal_group *se_tpg,
+static ssize_t sbp_tpg_attrib_max_logins_per_lun_show(struct config_item *item,
                char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        return sprintf(page, "%d\n", tport->max_logins_per_lun);
 }
 
-static ssize_t sbp_tpg_attrib_store_max_logins_per_lun(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t sbp_tpg_attrib_max_logins_per_lun_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct sbp_tpg *tpg = container_of(se_tpg, struct sbp_tpg, se_tpg);
        struct sbp_tport *tport = tpg->tport;
        unsigned long val;
@@ -2330,14 +2319,14 @@ static ssize_t sbp_tpg_attrib_store_max_logins_per_lun(
        return count;
 }
 
-TF_TPG_ATTRIB_ATTR(sbp, mgt_orb_timeout, S_IRUGO | S_IWUSR);
-TF_TPG_ATTRIB_ATTR(sbp, max_reconnect_timeout, S_IRUGO | S_IWUSR);
-TF_TPG_ATTRIB_ATTR(sbp, max_logins_per_lun, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(sbp_tpg_attrib_, mgt_orb_timeout);
+CONFIGFS_ATTR(sbp_tpg_attrib_, max_reconnect_timeout);
+CONFIGFS_ATTR(sbp_tpg_attrib_, max_logins_per_lun);
 
 static struct configfs_attribute *sbp_tpg_attrib_attrs[] = {
-       &sbp_tpg_attrib_mgt_orb_timeout.attr,
-       &sbp_tpg_attrib_max_reconnect_timeout.attr,
-       &sbp_tpg_attrib_max_logins_per_lun.attr,
+       &sbp_tpg_attrib_attr_mgt_orb_timeout,
+       &sbp_tpg_attrib_attr_max_reconnect_timeout,
+       &sbp_tpg_attrib_attr_max_logins_per_lun,
        NULL,
 };
 
index 860e840461778271191ba4ee8f1a4011dba5e78c..b9b9ffde4c7a870e32a623ad5aacbf289c07ebef 100644 (file)
@@ -40,8 +40,6 @@
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 
 #include "target_core_internal.h"
 #include "target_core_alua.h"
@@ -78,12 +76,6 @@ extern struct t10_alua_lu_gp *default_lu_gp;
 static LIST_HEAD(g_tf_list);
 static DEFINE_MUTEX(g_tf_lock);
 
-struct target_core_configfs_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(void *, char *);
-       ssize_t (*store)(void *, const char *, size_t);
-};
-
 static struct config_group target_core_hbagroup;
 static struct config_group alua_group;
 static struct config_group alua_lu_gps_group;
@@ -97,24 +89,15 @@ item_to_hba(struct config_item *item)
 /*
  * Attributes for /sys/kernel/config/target/
  */
-static ssize_t target_core_attr_show(struct config_item *item,
-                                     struct configfs_attribute *attr,
-                                     char *page)
+static ssize_t target_core_item_version_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "Target Engine Core ConfigFS Infrastructure %s"
                " on %s/%s on "UTS_RELEASE"\n", TARGET_CORE_VERSION,
                utsname()->sysname, utsname()->machine);
 }
 
-static struct configfs_item_operations target_core_fabric_item_ops = {
-       .show_attribute = target_core_attr_show,
-};
-
-static struct configfs_attribute target_core_item_attr_version = {
-       .ca_owner       = THIS_MODULE,
-       .ca_name        = "version",
-       .ca_mode        = S_IRUGO,
-};
+CONFIGFS_ATTR_RO(target_core_item_, version);
 
 static struct target_fabric_configfs *target_core_get_fabric(
        const char *name)
@@ -273,7 +256,6 @@ static struct configfs_attribute *target_core_fabric_item_attrs[] = {
  * Provides Fabrics Groups and Item Attributes for /sys/kernel/config/target/
  */
 static struct config_item_type target_core_fabrics_item = {
-       .ct_item_ops    = &target_core_fabric_item_ops,
        .ct_group_ops   = &target_core_fabric_group_ops,
        .ct_attrs       = target_core_fabric_item_attrs,
        .ct_owner       = THIS_MODULE,
@@ -476,47 +458,54 @@ EXPORT_SYMBOL(target_unregister_template);
 // Stop functions called by external Target Fabrics Modules
 //############################################################################*/
 
+static inline struct se_dev_attrib *to_attrib(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_dev_attrib,
+                       da_group);
+}
+
 /* Start functions for struct config_item_type tb_dev_attrib_cit */
-#define DEF_TB_DEV_ATTRIB_SHOW(_name)                                  \
-static ssize_t show_##_name(struct se_dev_attrib *da, char *page)      \
+#define DEF_CONFIGFS_ATTRIB_SHOW(_name)                                        \
+static ssize_t _name##_show(struct config_item *item, char *page)      \
 {                                                                      \
-       return snprintf(page, PAGE_SIZE, "%u\n", da->_name);            \
-}
-
-DEF_TB_DEV_ATTRIB_SHOW(emulate_model_alias);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_dpo);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_fua_write);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_fua_read);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_write_cache);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_ua_intlck_ctrl);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tas);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tpu);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_tpws);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_caw);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_3pc);
-DEF_TB_DEV_ATTRIB_SHOW(pi_prot_type);
-DEF_TB_DEV_ATTRIB_SHOW(hw_pi_prot_type);
-DEF_TB_DEV_ATTRIB_SHOW(pi_prot_format);
-DEF_TB_DEV_ATTRIB_SHOW(enforce_pr_isids);
-DEF_TB_DEV_ATTRIB_SHOW(is_nonrot);
-DEF_TB_DEV_ATTRIB_SHOW(emulate_rest_reord);
-DEF_TB_DEV_ATTRIB_SHOW(force_pr_aptpl);
-DEF_TB_DEV_ATTRIB_SHOW(hw_block_size);
-DEF_TB_DEV_ATTRIB_SHOW(block_size);
-DEF_TB_DEV_ATTRIB_SHOW(hw_max_sectors);
-DEF_TB_DEV_ATTRIB_SHOW(optimal_sectors);
-DEF_TB_DEV_ATTRIB_SHOW(hw_queue_depth);
-DEF_TB_DEV_ATTRIB_SHOW(queue_depth);
-DEF_TB_DEV_ATTRIB_SHOW(max_unmap_lba_count);
-DEF_TB_DEV_ATTRIB_SHOW(max_unmap_block_desc_count);
-DEF_TB_DEV_ATTRIB_SHOW(unmap_granularity);
-DEF_TB_DEV_ATTRIB_SHOW(unmap_granularity_alignment);
-DEF_TB_DEV_ATTRIB_SHOW(max_write_same_len);
-
-#define DEF_TB_DEV_ATTRIB_STORE_U32(_name)                             \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+       return snprintf(page, PAGE_SIZE, "%u\n", to_attrib(item)->_name); \
+}
+
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_model_alias);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_dpo);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_fua_write);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_fua_read);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_write_cache);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_ua_intlck_ctrl);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tas);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpu);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_tpws);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_caw);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_3pc);
+DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_type);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_pi_prot_type);
+DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_format);
+DEF_CONFIGFS_ATTRIB_SHOW(enforce_pr_isids);
+DEF_CONFIGFS_ATTRIB_SHOW(is_nonrot);
+DEF_CONFIGFS_ATTRIB_SHOW(emulate_rest_reord);
+DEF_CONFIGFS_ATTRIB_SHOW(force_pr_aptpl);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_block_size);
+DEF_CONFIGFS_ATTRIB_SHOW(block_size);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_max_sectors);
+DEF_CONFIGFS_ATTRIB_SHOW(optimal_sectors);
+DEF_CONFIGFS_ATTRIB_SHOW(hw_queue_depth);
+DEF_CONFIGFS_ATTRIB_SHOW(queue_depth);
+DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_lba_count);
+DEF_CONFIGFS_ATTRIB_SHOW(max_unmap_block_desc_count);
+DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity);
+DEF_CONFIGFS_ATTRIB_SHOW(unmap_granularity_alignment);
+DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
+
+#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name)                           \
+static ssize_t _name##_store(struct config_item *item, const char *page,\
                size_t count)                                           \
 {                                                                      \
+       struct se_dev_attrib *da = to_attrib(item);                     \
        u32 val;                                                        \
        int ret;                                                        \
                                                                        \
@@ -527,16 +516,17 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
        return count;                                                   \
 }
 
-DEF_TB_DEV_ATTRIB_STORE_U32(max_unmap_lba_count);
-DEF_TB_DEV_ATTRIB_STORE_U32(max_unmap_block_desc_count);
-DEF_TB_DEV_ATTRIB_STORE_U32(unmap_granularity);
-DEF_TB_DEV_ATTRIB_STORE_U32(unmap_granularity_alignment);
-DEF_TB_DEV_ATTRIB_STORE_U32(max_write_same_len);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_unmap_lba_count);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_unmap_block_desc_count);
+DEF_CONFIGFS_ATTRIB_STORE_U32(unmap_granularity);
+DEF_CONFIGFS_ATTRIB_STORE_U32(unmap_granularity_alignment);
+DEF_CONFIGFS_ATTRIB_STORE_U32(max_write_same_len);
 
-#define DEF_TB_DEV_ATTRIB_STORE_BOOL(_name)                            \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+#define DEF_CONFIGFS_ATTRIB_STORE_BOOL(_name)                          \
+static ssize_t _name##_store(struct config_item *item, const char *page,       \
                size_t count)                                           \
 {                                                                      \
+       struct se_dev_attrib *da = to_attrib(item);                     \
        bool flag;                                                      \
        int ret;                                                        \
                                                                        \
@@ -547,14 +537,14 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
        return count;                                                   \
 }
 
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_fua_write);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_caw);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(emulate_3pc);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(enforce_pr_isids);
-DEF_TB_DEV_ATTRIB_STORE_BOOL(is_nonrot);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_fua_write);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_caw);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(emulate_3pc);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(enforce_pr_isids);
+DEF_CONFIGFS_ATTRIB_STORE_BOOL(is_nonrot);
 
-#define DEF_TB_DEV_ATTRIB_STORE_STUB(_name)                            \
-static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
+#define DEF_CONFIGFS_ATTRIB_STORE_STUB(_name)                          \
+static ssize_t _name##_store(struct config_item *item, const char *page,\
                size_t count)                                           \
 {                                                                      \
        printk_once(KERN_WARNING                                        \
@@ -562,8 +552,8 @@ static ssize_t store_##_name(struct se_dev_attrib *da, const char *page,\
        return count;                                                   \
 }
 
-DEF_TB_DEV_ATTRIB_STORE_STUB(emulate_dpo);
-DEF_TB_DEV_ATTRIB_STORE_STUB(emulate_fua_read);
+DEF_CONFIGFS_ATTRIB_STORE_STUB(emulate_dpo);
+DEF_CONFIGFS_ATTRIB_STORE_STUB(emulate_fua_read);
 
 static void dev_set_t10_wwn_model_alias(struct se_device *dev)
 {
@@ -578,9 +568,10 @@ static void dev_set_t10_wwn_model_alias(struct se_device *dev)
        snprintf(&dev->t10_wwn.model[0], 16, "%s", configname);
 }
 
-static ssize_t store_emulate_model_alias(struct se_dev_attrib *da,
+static ssize_t emulate_model_alias_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        struct se_device *dev = da->da_dev;
        bool flag;
        int ret;
@@ -606,9 +597,10 @@ static ssize_t store_emulate_model_alias(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_write_cache(struct se_dev_attrib *da,
+static ssize_t emulate_write_cache_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -627,9 +619,10 @@ static ssize_t store_emulate_write_cache(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_ua_intlck_ctrl(struct se_dev_attrib *da,
+static ssize_t emulate_ua_intlck_ctrl_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        u32 val;
        int ret;
 
@@ -654,9 +647,10 @@ static ssize_t store_emulate_ua_intlck_ctrl(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_tas(struct se_dev_attrib *da,
+static ssize_t emulate_tas_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -677,9 +671,10 @@ static ssize_t store_emulate_tas(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_tpu(struct se_dev_attrib *da,
+static ssize_t emulate_tpu_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -702,9 +697,10 @@ static ssize_t store_emulate_tpu(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_tpws(struct se_dev_attrib *da,
+static ssize_t emulate_tpws_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -727,9 +723,10 @@ static ssize_t store_emulate_tpws(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_pi_prot_type(struct se_dev_attrib *da,
+static ssize_t pi_prot_type_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        int old_prot = da->pi_prot_type, ret;
        struct se_device *dev = da->da_dev;
        u32 flag;
@@ -787,9 +784,10 @@ static ssize_t store_pi_prot_type(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_pi_prot_format(struct se_dev_attrib *da,
+static ssize_t pi_prot_format_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        struct se_device *dev = da->da_dev;
        bool flag;
        int ret;
@@ -824,9 +822,10 @@ static ssize_t store_pi_prot_format(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_force_pr_aptpl(struct se_dev_attrib *da,
+static ssize_t force_pr_aptpl_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -845,9 +844,10 @@ static ssize_t store_force_pr_aptpl(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_emulate_rest_reord(struct se_dev_attrib *da,
+static ssize_t emulate_rest_reord_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        bool flag;
        int ret;
 
@@ -869,9 +869,10 @@ static ssize_t store_emulate_rest_reord(struct se_dev_attrib *da,
 /*
  * Note, this can only be called on unexported SE Device Object.
  */
-static ssize_t store_queue_depth(struct se_dev_attrib *da,
+static ssize_t queue_depth_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        struct se_device *dev = da->da_dev;
        u32 val;
        int ret;
@@ -905,9 +906,10 @@ static ssize_t store_queue_depth(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_optimal_sectors(struct se_dev_attrib *da,
+static ssize_t optimal_sectors_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        u32 val;
        int ret;
 
@@ -934,9 +936,10 @@ static ssize_t store_optimal_sectors(struct se_dev_attrib *da,
        return count;
 }
 
-static ssize_t store_block_size(struct se_dev_attrib *da,
+static ssize_t block_size_store(struct config_item *item,
                const char *page, size_t count)
 {
+       struct se_dev_attrib *da = to_attrib(item);
        u32 val;
        int ret;
 
@@ -967,50 +970,35 @@ static ssize_t store_block_size(struct se_dev_attrib *da,
        return count;
 }
 
-CONFIGFS_EATTR_STRUCT(target_backend_dev_attrib, se_dev_attrib);
-#define TB_DEV_ATTR(_backend, _name, _mode)                            \
-static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       show_##_name,                                                   \
-       store_##_name);
-
-#define TB_DEV_ATTR_RO(_backend, _name)                                        \
-static struct target_backend_dev_attrib_attribute _backend##_dev_attrib_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       show_##_name);
-
-TB_DEV_ATTR(target_core, emulate_model_alias, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_dpo, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_fua_write, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_fua_read, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_write_cache, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tas, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tpu, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_tpws, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_caw, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_3pc, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, pi_prot_type, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR_RO(target_core, hw_pi_prot_type);
-TB_DEV_ATTR(target_core, pi_prot_format, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, enforce_pr_isids, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, is_nonrot, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, emulate_rest_reord, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, force_pr_aptpl, S_IRUGO | S_IWUSR)
-TB_DEV_ATTR_RO(target_core, hw_block_size);
-TB_DEV_ATTR(target_core, block_size, S_IRUGO | S_IWUSR)
-TB_DEV_ATTR_RO(target_core, hw_max_sectors);
-TB_DEV_ATTR(target_core, optimal_sectors, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR_RO(target_core, hw_queue_depth);
-TB_DEV_ATTR(target_core, queue_depth, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_unmap_lba_count, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_unmap_block_desc_count, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, unmap_granularity, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, unmap_granularity_alignment, S_IRUGO | S_IWUSR);
-TB_DEV_ATTR(target_core, max_write_same_len, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_STRUCT(target_core_dev_attrib, se_dev_attrib);
-CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
+CONFIGFS_ATTR(, emulate_model_alias);
+CONFIGFS_ATTR(, emulate_dpo);
+CONFIGFS_ATTR(, emulate_fua_write);
+CONFIGFS_ATTR(, emulate_fua_read);
+CONFIGFS_ATTR(, emulate_write_cache);
+CONFIGFS_ATTR(, emulate_ua_intlck_ctrl);
+CONFIGFS_ATTR(, emulate_tas);
+CONFIGFS_ATTR(, emulate_tpu);
+CONFIGFS_ATTR(, emulate_tpws);
+CONFIGFS_ATTR(, emulate_caw);
+CONFIGFS_ATTR(, emulate_3pc);
+CONFIGFS_ATTR(, pi_prot_type);
+CONFIGFS_ATTR_RO(, hw_pi_prot_type);
+CONFIGFS_ATTR(, pi_prot_format);
+CONFIGFS_ATTR(, enforce_pr_isids);
+CONFIGFS_ATTR(, is_nonrot);
+CONFIGFS_ATTR(, emulate_rest_reord);
+CONFIGFS_ATTR(, force_pr_aptpl);
+CONFIGFS_ATTR_RO(, hw_block_size);
+CONFIGFS_ATTR(, block_size);
+CONFIGFS_ATTR_RO(, hw_max_sectors);
+CONFIGFS_ATTR(, optimal_sectors);
+CONFIGFS_ATTR_RO(, hw_queue_depth);
+CONFIGFS_ATTR(, queue_depth);
+CONFIGFS_ATTR(, max_unmap_lba_count);
+CONFIGFS_ATTR(, max_unmap_block_desc_count);
+CONFIGFS_ATTR(, unmap_granularity);
+CONFIGFS_ATTR(, unmap_granularity_alignment);
+CONFIGFS_ATTR(, max_write_same_len);
 
 /*
  * dev_attrib attributes for devices using the target core SBC/SPC
@@ -1018,100 +1006,78 @@ CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
  * these.
  */
 struct configfs_attribute *sbc_attrib_attrs[] = {
-       &target_core_dev_attrib_emulate_model_alias.attr,
-       &target_core_dev_attrib_emulate_dpo.attr,
-       &target_core_dev_attrib_emulate_fua_write.attr,
-       &target_core_dev_attrib_emulate_fua_read.attr,
-       &target_core_dev_attrib_emulate_write_cache.attr,
-       &target_core_dev_attrib_emulate_ua_intlck_ctrl.attr,
-       &target_core_dev_attrib_emulate_tas.attr,
-       &target_core_dev_attrib_emulate_tpu.attr,
-       &target_core_dev_attrib_emulate_tpws.attr,
-       &target_core_dev_attrib_emulate_caw.attr,
-       &target_core_dev_attrib_emulate_3pc.attr,
-       &target_core_dev_attrib_pi_prot_type.attr,
-       &target_core_dev_attrib_hw_pi_prot_type.attr,
-       &target_core_dev_attrib_pi_prot_format.attr,
-       &target_core_dev_attrib_enforce_pr_isids.attr,
-       &target_core_dev_attrib_is_nonrot.attr,
-       &target_core_dev_attrib_emulate_rest_reord.attr,
-       &target_core_dev_attrib_force_pr_aptpl.attr,
-       &target_core_dev_attrib_hw_block_size.attr,
-       &target_core_dev_attrib_block_size.attr,
-       &target_core_dev_attrib_hw_max_sectors.attr,
-       &target_core_dev_attrib_optimal_sectors.attr,
-       &target_core_dev_attrib_hw_queue_depth.attr,
-       &target_core_dev_attrib_queue_depth.attr,
-       &target_core_dev_attrib_max_unmap_lba_count.attr,
-       &target_core_dev_attrib_max_unmap_block_desc_count.attr,
-       &target_core_dev_attrib_unmap_granularity.attr,
-       &target_core_dev_attrib_unmap_granularity_alignment.attr,
-       &target_core_dev_attrib_max_write_same_len.attr,
+       &attr_emulate_model_alias,
+       &attr_emulate_dpo,
+       &attr_emulate_fua_write,
+       &attr_emulate_fua_read,
+       &attr_emulate_write_cache,
+       &attr_emulate_ua_intlck_ctrl,
+       &attr_emulate_tas,
+       &attr_emulate_tpu,
+       &attr_emulate_tpws,
+       &attr_emulate_caw,
+       &attr_emulate_3pc,
+       &attr_pi_prot_type,
+       &attr_hw_pi_prot_type,
+       &attr_pi_prot_format,
+       &attr_enforce_pr_isids,
+       &attr_is_nonrot,
+       &attr_emulate_rest_reord,
+       &attr_force_pr_aptpl,
+       &attr_hw_block_size,
+       &attr_block_size,
+       &attr_hw_max_sectors,
+       &attr_optimal_sectors,
+       &attr_hw_queue_depth,
+       &attr_queue_depth,
+       &attr_max_unmap_lba_count,
+       &attr_max_unmap_block_desc_count,
+       &attr_unmap_granularity,
+       &attr_unmap_granularity_alignment,
+       &attr_max_write_same_len,
        NULL,
 };
 EXPORT_SYMBOL(sbc_attrib_attrs);
 
-TB_DEV_ATTR_RO(target_pt, hw_pi_prot_type);
-TB_DEV_ATTR_RO(target_pt, hw_block_size);
-TB_DEV_ATTR_RO(target_pt, hw_max_sectors);
-TB_DEV_ATTR_RO(target_pt, hw_queue_depth);
-
 /*
  * Minimal dev_attrib attributes for devices passing through CDBs.
  * In this case we only provide a few read-only attributes for
  * backwards compatibility.
  */
 struct configfs_attribute *passthrough_attrib_attrs[] = {
-       &target_pt_dev_attrib_hw_pi_prot_type.attr,
-       &target_pt_dev_attrib_hw_block_size.attr,
-       &target_pt_dev_attrib_hw_max_sectors.attr,
-       &target_pt_dev_attrib_hw_queue_depth.attr,
+       &attr_hw_pi_prot_type,
+       &attr_hw_block_size,
+       &attr_hw_max_sectors,
+       &attr_hw_queue_depth,
        NULL,
 };
 EXPORT_SYMBOL(passthrough_attrib_attrs);
 
-static struct configfs_item_operations target_core_dev_attrib_ops = {
-       .show_attribute         = target_core_dev_attrib_attr_show,
-       .store_attribute        = target_core_dev_attrib_attr_store,
-};
-
-TB_CIT_SETUP_DRV(dev_attrib, &target_core_dev_attrib_ops, NULL);
+TB_CIT_SETUP_DRV(dev_attrib, NULL, NULL);
 
 /* End functions for struct config_item_type tb_dev_attrib_cit */
 
 /*  Start functions for struct config_item_type tb_dev_wwn_cit */
 
-CONFIGFS_EATTR_STRUCT(target_core_dev_wwn, t10_wwn);
-#define SE_DEV_WWN_ATTR(_name, _mode)                                  \
-static struct target_core_dev_wwn_attribute target_core_dev_wwn_##_name = \
-               __CONFIGFS_EATTR(_name, _mode,                          \
-               target_core_dev_wwn_show_attr_##_name,                  \
-               target_core_dev_wwn_store_attr_##_name);
-
-#define SE_DEV_WWN_ATTR_RO(_name);                                     \
-do {                                                                   \
-       static struct target_core_dev_wwn_attribute                     \
-                       target_core_dev_wwn_##_name =                   \
-               __CONFIGFS_EATTR_RO(_name,                              \
-               target_core_dev_wwn_show_attr_##_name);                 \
-} while (0);
+static struct t10_wwn *to_t10_wwn(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct t10_wwn, t10_wwn_group);
+}
 
 /*
  * VPD page 0x80 Unit serial
  */
-static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial(
-       struct t10_wwn *t10_wwn,
-       char *page)
+static ssize_t target_wwn_vpd_unit_serial_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "T10 VPD Unit Serial Number: %s\n",
-               &t10_wwn->unit_serial[0]);
+               &to_t10_wwn(item)->unit_serial[0]);
 }
 
-static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
-       struct t10_wwn *t10_wwn,
-       const char *page,
-       size_t count)
+static ssize_t target_wwn_vpd_unit_serial_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct t10_wwn *t10_wwn = to_t10_wwn(item);
        struct se_device *dev = t10_wwn->t10_dev;
        unsigned char buf[INQUIRY_VPD_SERIAL_LEN];
 
@@ -1167,15 +1133,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
        return count;
 }
 
-SE_DEV_WWN_ATTR(vpd_unit_serial, S_IRUGO | S_IWUSR);
-
 /*
  * VPD page 0x83 Protocol Identifier
  */
-static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
-       struct t10_wwn *t10_wwn,
-       char *page)
+static ssize_t target_wwn_vpd_protocol_identifier_show(struct config_item *item,
+               char *page)
 {
+       struct t10_wwn *t10_wwn = to_t10_wwn(item);
        struct t10_vpd *vpd;
        unsigned char buf[VPD_TMP_BUF_SIZE];
        ssize_t len = 0;
@@ -1199,25 +1163,15 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
        return len;
 }
 
-static ssize_t target_core_dev_wwn_store_attr_vpd_protocol_identifier(
-       struct t10_wwn *t10_wwn,
-       const char *page,
-       size_t count)
-{
-       return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_protocol_identifier, S_IRUGO | S_IWUSR);
-
 /*
  * Generic wrapper for dumping VPD identifiers by association.
  */
 #define DEF_DEV_WWN_ASSOC_SHOW(_name, _assoc)                          \
-static ssize_t target_core_dev_wwn_show_attr_##_name(                  \
-       struct t10_wwn *t10_wwn,                                        \
-       char *page)                                                     \
+static ssize_t target_wwn_##_name##_show(struct config_item *item,     \
+               char *page)                                             \
 {                                                                      \
-       struct t10_vpd *vpd;                                                    \
+       struct t10_wwn *t10_wwn = to_t10_wwn(item);                     \
+       struct t10_vpd *vpd;                                            \
        unsigned char buf[VPD_TMP_BUF_SIZE];                            \
        ssize_t len = 0;                                                \
                                                                        \
@@ -1249,84 +1203,39 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(                   \
        return len;                                                     \
 }
 
-/*
- * VPD page 0x83 Association: Logical Unit
- */
+/* VPD page 0x83 Association: Logical Unit */
 DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_logical_unit, 0x00);
-
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_logical_unit(
-       struct t10_wwn *t10_wwn,
-       const char *page,
-       size_t count)
-{
-       return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_logical_unit, S_IRUGO | S_IWUSR);
-
-/*
- * VPD page 0x83 Association: Target Port
- */
+/* VPD page 0x83 Association: Target Port */
 DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_target_port, 0x10);
-
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_target_port(
-       struct t10_wwn *t10_wwn,
-       const char *page,
-       size_t count)
-{
-       return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_target_port, S_IRUGO | S_IWUSR);
-
-/*
- * VPD page 0x83 Association: SCSI Target Device
- */
+/* VPD page 0x83 Association: SCSI Target Device */
 DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_scsi_target_device, 0x20);
 
-static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_scsi_target_device(
-       struct t10_wwn *t10_wwn,
-       const char *page,
-       size_t count)
-{
-       return -ENOSYS;
-}
-
-SE_DEV_WWN_ATTR(vpd_assoc_scsi_target_device, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_OPS(target_core_dev_wwn, t10_wwn, t10_wwn_group);
+CONFIGFS_ATTR(target_wwn_, vpd_unit_serial);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_protocol_identifier);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_logical_unit);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_target_port);
+CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_scsi_target_device);
 
 static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
-       &target_core_dev_wwn_vpd_unit_serial.attr,
-       &target_core_dev_wwn_vpd_protocol_identifier.attr,
-       &target_core_dev_wwn_vpd_assoc_logical_unit.attr,
-       &target_core_dev_wwn_vpd_assoc_target_port.attr,
-       &target_core_dev_wwn_vpd_assoc_scsi_target_device.attr,
+       &target_wwn_attr_vpd_unit_serial,
+       &target_wwn_attr_vpd_protocol_identifier,
+       &target_wwn_attr_vpd_assoc_logical_unit,
+       &target_wwn_attr_vpd_assoc_target_port,
+       &target_wwn_attr_vpd_assoc_scsi_target_device,
        NULL,
 };
 
-static struct configfs_item_operations target_core_dev_wwn_ops = {
-       .show_attribute         = target_core_dev_wwn_attr_show,
-       .store_attribute        = target_core_dev_wwn_attr_store,
-};
-
-TB_CIT_SETUP(dev_wwn, &target_core_dev_wwn_ops, NULL, target_core_dev_wwn_attrs);
+TB_CIT_SETUP(dev_wwn, NULL, NULL, target_core_dev_wwn_attrs);
 
 /*  End functions for struct config_item_type tb_dev_wwn_cit */
 
 /*  Start functions for struct config_item_type tb_dev_pr_cit */
 
-CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device);
-#define SE_DEV_PR_ATTR(_name, _mode)                                   \
-static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_core_dev_pr_show_attr_##_name,                           \
-       target_core_dev_pr_store_attr_##_name);
-
-#define SE_DEV_PR_ATTR_RO(_name);                                      \
-static struct target_core_dev_pr_attribute target_core_dev_pr_##_name =        \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_core_dev_pr_show_attr_##_name);
+static struct se_device *pr_to_dev(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_device,
+                       dev_pr_group);
+}
 
 static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev,
                char *page)
@@ -1367,9 +1276,9 @@ static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev,
        return len;
 }
 
-static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
-               char *page)
+static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
        int ret;
 
        if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
@@ -1384,11 +1293,10 @@ static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
        return ret;
 }
 
-SE_DEV_PR_ATTR_RO(res_holder);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_all_tgt_pts_show(struct config_item *item,
+               char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
        ssize_t len = 0;
 
        spin_lock(&dev->dev_reservation_lock);
@@ -1406,22 +1314,17 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
        return len;
 }
 
-SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_generation(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_generation_show(struct config_item *item,
+               char *page)
 {
-       return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation);
+       return sprintf(page, "0x%08x\n", pr_to_dev(item)->t10_pr.pr_generation);
 }
 
-SE_DEV_PR_ATTR_RO(res_pr_generation);
 
-/*
- * res_pr_holder_tg_port
- */
-static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_holder_tg_port_show(struct config_item *item,
+               char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
        struct se_node_acl *se_nacl;
        struct se_portal_group *se_tpg;
        struct t10_pr_registration *pr_reg;
@@ -1453,11 +1356,11 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
        return len;
 }
 
-SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port);
 
-static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_registered_i_pts_show(struct config_item *item,
+               char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
        const struct target_core_fabric_ops *tfo;
        struct t10_pr_registration *pr_reg;
        unsigned char buf[384];
@@ -1495,11 +1398,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
        return len;
 }
 
-SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts);
-
-static ssize_t target_core_dev_pr_show_attr_res_pr_type(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_pr_type_show(struct config_item *item, char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
        struct t10_pr_registration *pr_reg;
        ssize_t len = 0;
 
@@ -1516,11 +1417,10 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type(
        return len;
 }
 
-SE_DEV_PR_ATTR_RO(res_pr_type);
-
-static ssize_t target_core_dev_pr_show_attr_res_type(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
+
        if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
                return sprintf(page, "SPC_PASSTHROUGH\n");
        else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
@@ -1529,11 +1429,11 @@ static ssize_t target_core_dev_pr_show_attr_res_type(
                return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
 }
 
-SE_DEV_PR_ATTR_RO(res_type);
-
-static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
+               char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
+
        if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
                return 0;
 
@@ -1541,14 +1441,11 @@ static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
                (dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled");
 }
 
-SE_DEV_PR_ATTR_RO(res_aptpl_active);
-
-/*
- * res_aptpl_metadata
- */
-static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
-               struct se_device *dev, char *page)
+static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
+               char *page)
 {
+       struct se_device *dev = pr_to_dev(item);
+
        if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
                return 0;
 
@@ -1580,11 +1477,10 @@ static match_table_t tokens = {
        {Opt_err, NULL}
 };
 
-static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
-       struct se_device *dev,
-       const char *page,
-       size_t count)
+static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_device *dev = pr_to_dev(item);
        unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL;
        unsigned char *t_fabric = NULL, *t_port = NULL;
        char *orig, *ptr, *opts;
@@ -1765,37 +1661,44 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
        return (ret == 0) ? count : ret;
 }
 
-SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR);
 
-CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group);
+CONFIGFS_ATTR_RO(target_pr_, res_holder);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_all_tgt_pts);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_generation);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_holder_tg_port);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_registered_i_pts);
+CONFIGFS_ATTR_RO(target_pr_, res_pr_type);
+CONFIGFS_ATTR_RO(target_pr_, res_type);
+CONFIGFS_ATTR_RO(target_pr_, res_aptpl_active);
+CONFIGFS_ATTR(target_pr_, res_aptpl_metadata);
 
 static struct configfs_attribute *target_core_dev_pr_attrs[] = {
-       &target_core_dev_pr_res_holder.attr,
-       &target_core_dev_pr_res_pr_all_tgt_pts.attr,
-       &target_core_dev_pr_res_pr_generation.attr,
-       &target_core_dev_pr_res_pr_holder_tg_port.attr,
-       &target_core_dev_pr_res_pr_registered_i_pts.attr,
-       &target_core_dev_pr_res_pr_type.attr,
-       &target_core_dev_pr_res_type.attr,
-       &target_core_dev_pr_res_aptpl_active.attr,
-       &target_core_dev_pr_res_aptpl_metadata.attr,
+       &target_pr_attr_res_holder,
+       &target_pr_attr_res_pr_all_tgt_pts,
+       &target_pr_attr_res_pr_generation,
+       &target_pr_attr_res_pr_holder_tg_port,
+       &target_pr_attr_res_pr_registered_i_pts,
+       &target_pr_attr_res_pr_type,
+       &target_pr_attr_res_type,
+       &target_pr_attr_res_aptpl_active,
+       &target_pr_attr_res_aptpl_metadata,
        NULL,
 };
 
-static struct configfs_item_operations target_core_dev_pr_ops = {
-       .show_attribute         = target_core_dev_pr_attr_show,
-       .store_attribute        = target_core_dev_pr_attr_store,
-};
-
-TB_CIT_SETUP(dev_pr, &target_core_dev_pr_ops, NULL, target_core_dev_pr_attrs);
+TB_CIT_SETUP(dev_pr, NULL, NULL, target_core_dev_pr_attrs);
 
 /*  End functions for struct config_item_type tb_dev_pr_cit */
 
 /*  Start functions for struct config_item_type tb_dev_cit */
 
-static ssize_t target_core_show_dev_info(void *p, char *page)
+static inline struct se_device *to_device(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_device, dev_group);
+}
+
+static ssize_t target_dev_info_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        int bl = 0;
        ssize_t read_bytes = 0;
 
@@ -1806,35 +1709,17 @@ static ssize_t target_core_show_dev_info(void *p, char *page)
        return read_bytes;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_info = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "info",
-                   .ca_mode = S_IRUGO },
-       .show   = target_core_show_dev_info,
-       .store  = NULL,
-};
-
-static ssize_t target_core_store_dev_control(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_control_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
 
        return dev->transport->set_configfs_dev_params(dev, page, count);
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_control = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "control",
-                   .ca_mode = S_IWUSR },
-       .show   = NULL,
-       .store  = target_core_store_dev_control,
-};
-
-static ssize_t target_core_show_dev_alias(void *p, char *page)
+static ssize_t target_dev_alias_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
 
        if (!(dev->dev_flags & DF_USING_ALIAS))
                return 0;
@@ -1842,12 +1727,10 @@ static ssize_t target_core_show_dev_alias(void *p, char *page)
        return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias);
 }
 
-static ssize_t target_core_store_dev_alias(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_alias_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct se_hba *hba = dev->se_hba;
        ssize_t read_bytes;
 
@@ -1874,17 +1757,9 @@ static ssize_t target_core_store_dev_alias(
        return read_bytes;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_alias = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "alias",
-                   .ca_mode =  S_IRUGO | S_IWUSR },
-       .show   = target_core_show_dev_alias,
-       .store  = target_core_store_dev_alias,
-};
-
-static ssize_t target_core_show_dev_udev_path(void *p, char *page)
+static ssize_t target_dev_udev_path_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
 
        if (!(dev->dev_flags & DF_USING_UDEV_PATH))
                return 0;
@@ -1892,12 +1767,10 @@ static ssize_t target_core_show_dev_udev_path(void *p, char *page)
        return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path);
 }
 
-static ssize_t target_core_store_dev_udev_path(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_udev_path_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct se_hba *hba = dev->se_hba;
        ssize_t read_bytes;
 
@@ -1925,27 +1798,17 @@ static ssize_t target_core_store_dev_udev_path(
        return read_bytes;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_udev_path = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "udev_path",
-                   .ca_mode =  S_IRUGO | S_IWUSR },
-       .show   = target_core_show_dev_udev_path,
-       .store  = target_core_store_dev_udev_path,
-};
-
-static ssize_t target_core_show_dev_enable(void *p, char *page)
+static ssize_t target_dev_enable_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
 
        return snprintf(page, PAGE_SIZE, "%d\n", !!(dev->dev_flags & DF_CONFIGURED));
 }
 
-static ssize_t target_core_store_dev_enable(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        char *ptr;
        int ret;
 
@@ -1962,17 +1825,9 @@ static ssize_t target_core_store_dev_enable(
        return count;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_enable = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "enable",
-                   .ca_mode =  S_IRUGO | S_IWUSR },
-       .show   = target_core_show_dev_enable,
-       .store  = target_core_store_dev_enable,
-};
-
-static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
+static ssize_t target_dev_alua_lu_gp_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct config_item *lu_ci;
        struct t10_alua_lu_gp *lu_gp;
        struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -1994,12 +1849,10 @@ static ssize_t target_core_show_alua_lu_gp(void *p, char *page)
        return len;
 }
 
-static ssize_t target_core_store_alua_lu_gp(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_alua_lu_gp_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct se_hba *hba = dev->se_hba;
        struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL;
        struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -2076,17 +1929,9 @@ static ssize_t target_core_store_alua_lu_gp(
        return count;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "alua_lu_gp",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = target_core_show_alua_lu_gp,
-       .store  = target_core_store_alua_lu_gp,
-};
-
-static ssize_t target_core_show_dev_lba_map(void *p, char *page)
+static ssize_t target_dev_lba_map_show(struct config_item *item, char *page)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct t10_alua_lba_map *map;
        struct t10_alua_lba_map_member *mem;
        char *b = page;
@@ -2129,12 +1974,10 @@ static ssize_t target_core_show_dev_lba_map(void *p, char *page)
        return bl;
 }
 
-static ssize_t target_core_store_dev_lba_map(
-       void *p,
-       const char *page,
-       size_t count)
+static ssize_t target_dev_lba_map_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       struct se_device *dev = p;
+       struct se_device *dev = to_device(item);
        struct t10_alua_lba_map *lba_map = NULL;
        struct list_head lba_list;
        char *map_entries, *ptr;
@@ -2246,22 +2089,22 @@ static ssize_t target_core_store_dev_lba_map(
        return count;
 }
 
-static struct target_core_configfs_attribute target_core_attr_dev_lba_map = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "lba_map",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = target_core_show_dev_lba_map,
-       .store  = target_core_store_dev_lba_map,
-};
+CONFIGFS_ATTR_RO(target_dev_, info);
+CONFIGFS_ATTR_WO(target_dev_, control);
+CONFIGFS_ATTR(target_dev_, alias);
+CONFIGFS_ATTR(target_dev_, udev_path);
+CONFIGFS_ATTR(target_dev_, enable);
+CONFIGFS_ATTR(target_dev_, alua_lu_gp);
+CONFIGFS_ATTR(target_dev_, lba_map);
 
 static struct configfs_attribute *target_core_dev_attrs[] = {
-       &target_core_attr_dev_info.attr,
-       &target_core_attr_dev_control.attr,
-       &target_core_attr_dev_alias.attr,
-       &target_core_attr_dev_udev_path.attr,
-       &target_core_attr_dev_enable.attr,
-       &target_core_attr_dev_alua_lu_gp.attr,
-       &target_core_attr_dev_lba_map.attr,
+       &target_dev_attr_info,
+       &target_dev_attr_control,
+       &target_dev_attr_alias,
+       &target_dev_attr_udev_path,
+       &target_dev_attr_enable,
+       &target_dev_attr_alua_lu_gp,
+       &target_dev_attr_lba_map,
        NULL,
 };
 
@@ -2275,42 +2118,8 @@ static void target_core_dev_release(struct config_item *item)
        target_free_device(dev);
 }
 
-static ssize_t target_core_dev_show(struct config_item *item,
-                                    struct configfs_attribute *attr,
-                                    char *page)
-{
-       struct config_group *dev_cg = to_config_group(item);
-       struct se_device *dev =
-               container_of(dev_cg, struct se_device, dev_group);
-       struct target_core_configfs_attribute *tc_attr = container_of(
-                       attr, struct target_core_configfs_attribute, attr);
-
-       if (!tc_attr->show)
-               return -EINVAL;
-
-       return tc_attr->show(dev, page);
-}
-
-static ssize_t target_core_dev_store(struct config_item *item,
-                                     struct configfs_attribute *attr,
-                                     const char *page, size_t count)
-{
-       struct config_group *dev_cg = to_config_group(item);
-       struct se_device *dev =
-               container_of(dev_cg, struct se_device, dev_group);
-       struct target_core_configfs_attribute *tc_attr = container_of(
-                       attr, struct target_core_configfs_attribute, attr);
-
-       if (!tc_attr->store)
-               return -EINVAL;
-
-       return tc_attr->store(dev, page, count);
-}
-
 static struct configfs_item_operations target_core_dev_item_ops = {
        .release                = target_core_dev_release,
-       .show_attribute         = target_core_dev_show,
-       .store_attribute        = target_core_dev_store,
 };
 
 TB_CIT_SETUP(dev, &target_core_dev_item_ops, NULL, target_core_dev_attrs);
@@ -2319,38 +2128,25 @@ TB_CIT_SETUP(dev, &target_core_dev_item_ops, NULL, target_core_dev_attrs);
 
 /* Start functions for struct config_item_type target_core_alua_lu_gp_cit */
 
-CONFIGFS_EATTR_STRUCT(target_core_alua_lu_gp, t10_alua_lu_gp);
-#define SE_DEV_ALUA_LU_ATTR(_name, _mode)                              \
-static struct target_core_alua_lu_gp_attribute                         \
-                       target_core_alua_lu_gp_##_name =                \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_core_alua_lu_gp_show_attr_##_name,                       \
-       target_core_alua_lu_gp_store_attr_##_name);
-
-#define SE_DEV_ALUA_LU_ATTR_RO(_name)                                  \
-static struct target_core_alua_lu_gp_attribute                         \
-                       target_core_alua_lu_gp_##_name =                \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_core_alua_lu_gp_show_attr_##_name);
+static inline struct t10_alua_lu_gp *to_lu_gp(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct t10_alua_lu_gp,
+                       lu_gp_group);
+}
 
-/*
- * lu_gp_id
- */
-static ssize_t target_core_alua_lu_gp_show_attr_lu_gp_id(
-       struct t10_alua_lu_gp *lu_gp,
-       char *page)
+static ssize_t target_lu_gp_lu_gp_id_show(struct config_item *item, char *page)
 {
+       struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
+
        if (!lu_gp->lu_gp_valid_id)
                return 0;
-
        return sprintf(page, "%hu\n", lu_gp->lu_gp_id);
 }
 
-static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
-       struct t10_alua_lu_gp *lu_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_lu_gp_lu_gp_id_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
        struct config_group *alua_lu_gp_cg = &lu_gp->lu_gp_group;
        unsigned long lu_gp_id;
        int ret;
@@ -2379,15 +2175,9 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id(
        return count;
 }
 
-SE_DEV_ALUA_LU_ATTR(lu_gp_id, S_IRUGO | S_IWUSR);
-
-/*
- * members
- */
-static ssize_t target_core_alua_lu_gp_show_attr_members(
-       struct t10_alua_lu_gp *lu_gp,
-       char *page)
+static ssize_t target_lu_gp_members_show(struct config_item *item, char *page)
 {
+       struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
        struct se_device *dev;
        struct se_hba *hba;
        struct t10_alua_lu_gp_member *lu_gp_mem;
@@ -2419,13 +2209,12 @@ static ssize_t target_core_alua_lu_gp_show_attr_members(
        return len;
 }
 
-SE_DEV_ALUA_LU_ATTR_RO(members);
-
-CONFIGFS_EATTR_OPS(target_core_alua_lu_gp, t10_alua_lu_gp, lu_gp_group);
+CONFIGFS_ATTR(target_lu_gp_, lu_gp_id);
+CONFIGFS_ATTR_RO(target_lu_gp_, members);
 
 static struct configfs_attribute *target_core_alua_lu_gp_attrs[] = {
-       &target_core_alua_lu_gp_lu_gp_id.attr,
-       &target_core_alua_lu_gp_members.attr,
+       &target_lu_gp_attr_lu_gp_id,
+       &target_lu_gp_attr_members,
        NULL,
 };
 
@@ -2439,8 +2228,6 @@ static void target_core_alua_lu_gp_release(struct config_item *item)
 
 static struct configfs_item_operations target_core_alua_lu_gp_ops = {
        .release                = target_core_alua_lu_gp_release,
-       .show_attribute         = target_core_alua_lu_gp_attr_show,
-       .store_attribute        = target_core_alua_lu_gp_attr_store,
 };
 
 static struct config_item_type target_core_alua_lu_gp_cit = {
@@ -2511,36 +2298,23 @@ static struct config_item_type target_core_alua_lu_gps_cit = {
 
 /* Start functions for struct config_item_type target_core_alua_tg_pt_gp_cit */
 
-CONFIGFS_EATTR_STRUCT(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp);
-#define SE_DEV_ALUA_TG_PT_ATTR(_name, _mode)                           \
-static struct target_core_alua_tg_pt_gp_attribute                      \
-                       target_core_alua_tg_pt_gp_##_name =             \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_core_alua_tg_pt_gp_show_attr_##_name,                    \
-       target_core_alua_tg_pt_gp_store_attr_##_name);
-
-#define SE_DEV_ALUA_TG_PT_ATTR_RO(_name)                               \
-static struct target_core_alua_tg_pt_gp_attribute                      \
-                       target_core_alua_tg_pt_gp_##_name =             \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_core_alua_tg_pt_gp_show_attr_##_name);
+static inline struct t10_alua_tg_pt_gp *to_tg_pt_gp(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct t10_alua_tg_pt_gp,
+                       tg_pt_gp_group);
+}
 
-/*
- * alua_access_state
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_state(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_alua_access_state_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "%d\n",
-               atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state));
+               atomic_read(&to_tg_pt_gp(item)->tg_pt_gp_alua_access_state));
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_alua_access_state_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        struct se_device *dev = tg_pt_gp->tg_pt_gp_dev;
        unsigned long tmp;
        int new_state, ret;
@@ -2582,24 +2356,18 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state(
        return (!ret) ? count : -EINVAL;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_state, S_IRUGO | S_IWUSR);
-
-/*
- * alua_access_status
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_status(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_alua_access_status_show(struct config_item *item,
+               char *page)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        return sprintf(page, "%s\n",
                core_alua_dump_status(tg_pt_gp->tg_pt_gp_alua_access_status));
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_alua_access_status_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        unsigned long tmp;
        int new_status, ret;
 
@@ -2630,43 +2398,31 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status(
        return count;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_status, S_IRUGO | S_IWUSR);
-
-/*
- * alua_access_type
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_type(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_alua_access_type_show(struct config_item *item,
+               char *page)
 {
-       return core_alua_show_access_type(tg_pt_gp, page);
+       return core_alua_show_access_type(to_tg_pt_gp(item), page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_alua_access_type_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       return core_alua_store_access_type(tg_pt_gp, page, count);
+       return core_alua_store_access_type(to_tg_pt_gp(item), page, count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR);
-
-/*
- * alua_supported_states
- */
-
-#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit)              \
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \
-       struct t10_alua_tg_pt_gp *t, char *p)                           \
+#define ALUA_SUPPORTED_STATE_ATTR(_name, _bit)                         \
+static ssize_t target_tg_pt_gp_alua_support_##_name##_show(            \
+               struct config_item *item, char *p)                      \
 {                                                                      \
-       return sprintf(p, "%d\n", !!(t->_var & _bit));                  \
-}
-
-#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit)             \
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
-       struct t10_alua_tg_pt_gp *t, const char *p, size_t c)           \
+       struct t10_alua_tg_pt_gp *t = to_tg_pt_gp(item);                \
+       return sprintf(p, "%d\n",                                       \
+               !!(t->tg_pt_gp_alua_supported_states & _bit));          \
+}                                                                      \
+                                                                       \
+static ssize_t target_tg_pt_gp_alua_support_##_name##_store(           \
+               struct config_item *item, const char *p, size_t c)      \
 {                                                                      \
+       struct t10_alua_tg_pt_gp *t = to_tg_pt_gp(item);                \
        unsigned long tmp;                                              \
        int ret;                                                        \
                                                                        \
@@ -2687,70 +2443,32 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\
                return -EINVAL;                                         \
        }                                                               \
        if (tmp)                                                        \
-               t->_var |= _bit;                                        \
+               t->tg_pt_gp_alua_supported_states |= _bit;              \
        else                                                            \
-               t->_var &= ~_bit;                                       \
+               t->tg_pt_gp_alua_supported_states &= ~_bit;             \
                                                                        \
        return c;                                                       \
 }
 
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning,
-                              tg_pt_gp_alua_supported_states, ALUA_T_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning,
-                               tg_pt_gp_alua_supported_states, ALUA_T_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline,
-                              tg_pt_gp_alua_supported_states, ALUA_O_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(offline,
-                               tg_pt_gp_alua_supported_states, ALUA_O_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent,
-                              tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent,
-                               tg_pt_gp_alua_supported_states, ALUA_LBD_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable,
-                              tg_pt_gp_alua_supported_states, ALUA_U_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable,
-                               tg_pt_gp_alua_supported_states, ALUA_U_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby,
-                              tg_pt_gp_alua_supported_states, ALUA_S_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(standby,
-                               tg_pt_gp_alua_supported_states, ALUA_S_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized,
-                              tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized,
-                               tg_pt_gp_alua_supported_states, ALUA_AO_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR);
-
-SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized,
-                              tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
-SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized,
-                               tg_pt_gp_alua_supported_states, ALUA_AN_SUP);
-SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR);
+ALUA_SUPPORTED_STATE_ATTR(transitioning, ALUA_T_SUP);
+ALUA_SUPPORTED_STATE_ATTR(offline, ALUA_O_SUP);
+ALUA_SUPPORTED_STATE_ATTR(lba_dependent, ALUA_LBD_SUP);
+ALUA_SUPPORTED_STATE_ATTR(unavailable, ALUA_U_SUP);
+ALUA_SUPPORTED_STATE_ATTR(standby, ALUA_S_SUP);
+ALUA_SUPPORTED_STATE_ATTR(active_optimized, ALUA_AO_SUP);
+ALUA_SUPPORTED_STATE_ATTR(active_nonoptimized, ALUA_AN_SUP);
 
-/*
- * alua_write_metadata
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_alua_write_metadata_show(
+               struct config_item *item, char *page)
 {
-       return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_write_metadata);
+       return sprintf(page, "%d\n",
+               to_tg_pt_gp(item)->tg_pt_gp_write_metadata);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_alua_write_metadata_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        unsigned long tmp;
        int ret;
 
@@ -2770,110 +2488,71 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata(
        return count;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(alua_write_metadata, S_IRUGO | S_IWUSR);
-
-
-
-/*
- * nonop_delay_msecs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_nonop_delay_msecs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_nonop_delay_msecs_show(struct config_item *item,
+               char *page)
 {
-       return core_alua_show_nonop_delay_msecs(tg_pt_gp, page);
-
+       return core_alua_show_nonop_delay_msecs(to_tg_pt_gp(item), page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_nonop_delay_msecs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_nonop_delay_msecs_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       return core_alua_store_nonop_delay_msecs(tg_pt_gp, page, count);
+       return core_alua_store_nonop_delay_msecs(to_tg_pt_gp(item), page,
+                       count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(nonop_delay_msecs, S_IRUGO | S_IWUSR);
-
-/*
- * trans_delay_msecs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_trans_delay_msecs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_trans_delay_msecs_show(struct config_item *item,
+               char *page)
 {
-       return core_alua_show_trans_delay_msecs(tg_pt_gp, page);
+       return core_alua_show_trans_delay_msecs(to_tg_pt_gp(item), page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_trans_delay_msecs_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       return core_alua_store_trans_delay_msecs(tg_pt_gp, page, count);
+       return core_alua_store_trans_delay_msecs(to_tg_pt_gp(item), page,
+                       count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
-
-/*
- * implicit_trans_secs
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_implicit_trans_secs_show(
+               struct config_item *item, char *page)
 {
-       return core_alua_show_implicit_trans_secs(tg_pt_gp, page);
+       return core_alua_show_implicit_trans_secs(to_tg_pt_gp(item), page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_implicit_trans_secs_store(
+               struct config_item *item, const char *page, size_t count)
 {
-       return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count);
+       return core_alua_store_implicit_trans_secs(to_tg_pt_gp(item), page,
+                       count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR);
-
-/*
- * preferred
- */
-
-static ssize_t target_core_alua_tg_pt_gp_show_attr_preferred(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_preferred_show(struct config_item *item,
+               char *page)
 {
-       return core_alua_show_preferred_bit(tg_pt_gp, page);
+       return core_alua_show_preferred_bit(to_tg_pt_gp(item), page);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_preferred(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_preferred_store(struct config_item *item,
+               const char *page, size_t count)
 {
-       return core_alua_store_preferred_bit(tg_pt_gp, page, count);
+       return core_alua_store_preferred_bit(to_tg_pt_gp(item), page, count);
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(preferred, S_IRUGO | S_IWUSR);
-
-/*
- * tg_pt_gp_id
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_tg_pt_gp_id(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_tg_pt_gp_id_show(struct config_item *item,
+               char *page)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
+
        if (!tg_pt_gp->tg_pt_gp_valid_id)
                return 0;
-
        return sprintf(page, "%hu\n", tg_pt_gp->tg_pt_gp_id);
 }
 
-static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       const char *page,
-       size_t count)
+static ssize_t target_tg_pt_gp_tg_pt_gp_id_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        struct config_group *alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group;
        unsigned long tg_pt_gp_id;
        int ret;
@@ -2902,15 +2581,10 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id(
        return count;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR(tg_pt_gp_id, S_IRUGO | S_IWUSR);
-
-/*
- * members
- */
-static ssize_t target_core_alua_tg_pt_gp_show_attr_members(
-       struct t10_alua_tg_pt_gp *tg_pt_gp,
-       char *page)
+static ssize_t target_tg_pt_gp_members_show(struct config_item *item,
+               char *page)
 {
+       struct t10_alua_tg_pt_gp *tg_pt_gp = to_tg_pt_gp(item);
        struct se_lun *lun;
        ssize_t len = 0, cur_len;
        unsigned char buf[TG_PT_GROUP_NAME_BUF];
@@ -2942,29 +2616,42 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_members(
        return len;
 }
 
-SE_DEV_ALUA_TG_PT_ATTR_RO(members);
-
-CONFIGFS_EATTR_OPS(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp,
-                       tg_pt_gp_group);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_state);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_status);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_access_type);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_transitioning);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_offline);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_lba_dependent);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_unavailable);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_standby);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_active_optimized);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_support_active_nonoptimized);
+CONFIGFS_ATTR(target_tg_pt_gp_, alua_write_metadata);
+CONFIGFS_ATTR(target_tg_pt_gp_, nonop_delay_msecs);
+CONFIGFS_ATTR(target_tg_pt_gp_, trans_delay_msecs);
+CONFIGFS_ATTR(target_tg_pt_gp_, implicit_trans_secs);
+CONFIGFS_ATTR(target_tg_pt_gp_, preferred);
+CONFIGFS_ATTR(target_tg_pt_gp_, tg_pt_gp_id);
+CONFIGFS_ATTR_RO(target_tg_pt_gp_, members);
 
 static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
-       &target_core_alua_tg_pt_gp_alua_access_state.attr,
-       &target_core_alua_tg_pt_gp_alua_access_status.attr,
-       &target_core_alua_tg_pt_gp_alua_access_type.attr,
-       &target_core_alua_tg_pt_gp_alua_support_transitioning.attr,
-       &target_core_alua_tg_pt_gp_alua_support_offline.attr,
-       &target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr,
-       &target_core_alua_tg_pt_gp_alua_support_unavailable.attr,
-       &target_core_alua_tg_pt_gp_alua_support_standby.attr,
-       &target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr,
-       &target_core_alua_tg_pt_gp_alua_support_active_optimized.attr,
-       &target_core_alua_tg_pt_gp_alua_write_metadata.attr,
-       &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
-       &target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
-       &target_core_alua_tg_pt_gp_implicit_trans_secs.attr,
-       &target_core_alua_tg_pt_gp_preferred.attr,
-       &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
-       &target_core_alua_tg_pt_gp_members.attr,
+       &target_tg_pt_gp_attr_alua_access_state,
+       &target_tg_pt_gp_attr_alua_access_status,
+       &target_tg_pt_gp_attr_alua_access_type,
+       &target_tg_pt_gp_attr_alua_support_transitioning,
+       &target_tg_pt_gp_attr_alua_support_offline,
+       &target_tg_pt_gp_attr_alua_support_lba_dependent,
+       &target_tg_pt_gp_attr_alua_support_unavailable,
+       &target_tg_pt_gp_attr_alua_support_standby,
+       &target_tg_pt_gp_attr_alua_support_active_nonoptimized,
+       &target_tg_pt_gp_attr_alua_support_active_optimized,
+       &target_tg_pt_gp_attr_alua_write_metadata,
+       &target_tg_pt_gp_attr_nonop_delay_msecs,
+       &target_tg_pt_gp_attr_trans_delay_msecs,
+       &target_tg_pt_gp_attr_implicit_trans_secs,
+       &target_tg_pt_gp_attr_preferred,
+       &target_tg_pt_gp_attr_tg_pt_gp_id,
+       &target_tg_pt_gp_attr_members,
        NULL,
 };
 
@@ -2978,8 +2665,6 @@ static void target_core_alua_tg_pt_gp_release(struct config_item *item)
 
 static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = {
        .release                = target_core_alua_tg_pt_gp_release,
-       .show_attribute         = target_core_alua_tg_pt_gp_attr_show,
-       .store_attribute        = target_core_alua_tg_pt_gp_attr_store,
 };
 
 static struct config_item_type target_core_alua_tg_pt_gp_cit = {
@@ -3237,34 +2922,24 @@ static struct configfs_group_operations target_core_hba_group_ops = {
        .drop_item              = target_core_drop_subdev,
 };
 
-CONFIGFS_EATTR_STRUCT(target_core_hba, se_hba);
-#define SE_HBA_ATTR(_name, _mode)                              \
-static struct target_core_hba_attribute                                \
-               target_core_hba_##_name =                       \
-               __CONFIGFS_EATTR(_name, _mode,                  \
-               target_core_hba_show_attr_##_name,              \
-               target_core_hba_store_attr_##_name);
 
-#define SE_HBA_ATTR_RO(_name)                                  \
-static struct target_core_hba_attribute                                \
-               target_core_hba_##_name =                       \
-               __CONFIGFS_EATTR_RO(_name,                      \
-               target_core_hba_show_attr_##_name);
+static inline struct se_hba *to_hba(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_hba, hba_group);
+}
 
-static ssize_t target_core_hba_show_attr_hba_info(
-       struct se_hba *hba,
-       char *page)
+static ssize_t target_hba_info_show(struct config_item *item, char *page)
 {
+       struct se_hba *hba = to_hba(item);
+
        return sprintf(page, "HBA Index: %d plugin: %s version: %s\n",
                        hba->hba_id, hba->backend->ops->name,
                        TARGET_CORE_VERSION);
 }
 
-SE_HBA_ATTR_RO(hba_info);
-
-static ssize_t target_core_hba_show_attr_hba_mode(struct se_hba *hba,
-                               char *page)
+static ssize_t target_hba_mode_show(struct config_item *item, char *page)
 {
+       struct se_hba *hba = to_hba(item);
        int hba_mode = 0;
 
        if (hba->hba_flags & HBA_FLAGS_PSCSI_MODE)
@@ -3273,9 +2948,10 @@ static ssize_t target_core_hba_show_attr_hba_mode(struct se_hba *hba,
        return sprintf(page, "%d\n", hba_mode);
 }
 
-static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
-                               const char *page, size_t count)
+static ssize_t target_hba_mode_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_hba *hba = to_hba(item);
        unsigned long mode_flag;
        int ret;
 
@@ -3304,9 +2980,8 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba,
        return count;
 }
 
-SE_HBA_ATTR(hba_mode, S_IRUGO | S_IWUSR);
-
-CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group);
+CONFIGFS_ATTR_RO(target_, hba_info);
+CONFIGFS_ATTR(target_, hba_mode);
 
 static void target_core_hba_release(struct config_item *item)
 {
@@ -3316,15 +2991,13 @@ static void target_core_hba_release(struct config_item *item)
 }
 
 static struct configfs_attribute *target_core_hba_attrs[] = {
-       &target_core_hba_hba_info.attr,
-       &target_core_hba_hba_mode.attr,
+       &target_attr_hba_info,
+       &target_attr_hba_mode,
        NULL,
 };
 
 static struct configfs_item_operations target_core_hba_item_ops = {
        .release                = target_core_hba_release,
-       .show_attribute         = target_core_hba_attr_show,
-       .store_attribute        = target_core_hba_attr_store,
 };
 
 static struct config_item_type target_core_hba_cit = {
index be42429468e2505833f0578eea2cf5a81a4f9ee0..f916d18ccb487c0910ec79ec3f0d8dda232a7b30 100644 (file)
@@ -35,8 +35,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 
 #include "target_core_internal.h"
 #include "target_core_alua.h"
@@ -152,17 +150,16 @@ static int target_fabric_mappedlun_unlink(
        return core_dev_del_initiator_node_lun_acl(lun, lacl);
 }
 
-CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl);
-#define TCM_MAPPEDLUN_ATTR(_name, _mode)                               \
-static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_fabric_mappedlun_show_##_name,                           \
-       target_fabric_mappedlun_store_##_name);
+static struct se_lun_acl *item_to_lun_acl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_lun_acl,
+                       se_lun_group);
+}
 
-static ssize_t target_fabric_mappedlun_show_write_protect(
-       struct se_lun_acl *lacl,
-       char *page)
+static ssize_t target_fabric_mappedlun_write_protect_show(
+               struct config_item *item, char *page)
 {
+       struct se_lun_acl *lacl = item_to_lun_acl(item);
        struct se_node_acl *se_nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t len = 0;
@@ -178,11 +175,10 @@ static ssize_t target_fabric_mappedlun_show_write_protect(
        return len;
 }
 
-static ssize_t target_fabric_mappedlun_store_write_protect(
-       struct se_lun_acl *lacl,
-       const char *page,
-       size_t count)
+static ssize_t target_fabric_mappedlun_write_protect_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_lun_acl *lacl = item_to_lun_acl(item);
        struct se_node_acl *se_nacl = lacl->se_lun_nacl;
        struct se_portal_group *se_tpg = se_nacl->se_tpg;
        unsigned long op;
@@ -209,9 +205,12 @@ static ssize_t target_fabric_mappedlun_store_write_protect(
 
 }
 
-TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(target_fabric_mappedlun_, write_protect);
 
-CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group);
+static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
+       &target_fabric_mappedlun_attr_write_protect,
+       NULL,
+};
 
 static void target_fabric_mappedlun_release(struct config_item *item)
 {
@@ -222,15 +221,8 @@ static void target_fabric_mappedlun_release(struct config_item *item)
        core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
 }
 
-static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
-       &target_fabric_mappedlun_write_protect.attr,
-       NULL,
-};
-
 static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
        .release                = target_fabric_mappedlun_release,
-       .show_attribute         = target_fabric_mappedlun_attr_show,
-       .store_attribute        = target_fabric_mappedlun_attr_store,
        .allow_link             = target_fabric_mappedlun_link,
        .drop_link              = target_fabric_mappedlun_unlink,
 };
@@ -266,49 +258,12 @@ TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
 
 /* End of tfc_tpg_mappedlun_port_cit */
 
-/* Start of tfc_tpg_nacl_attrib_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
-
-static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
-       .show_attribute         = target_fabric_nacl_attrib_attr_show,
-       .store_attribute        = target_fabric_nacl_attrib_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_attrib_cit */
-
-/* Start of tfc_tpg_nacl_auth_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group);
-
-static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
-       .show_attribute         = target_fabric_nacl_auth_attr_show,
-       .store_attribute        = target_fabric_nacl_auth_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_auth_cit */
-
-/* Start of tfc_tpg_nacl_param_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group);
-
-static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
-       .show_attribute         = target_fabric_nacl_param_attr_show,
-       .store_attribute        = target_fabric_nacl_param_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL);
-
-/* End of tfc_tpg_nacl_param_cit */
+TF_CIT_SETUP_DRV(tpg_nacl_attrib, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_auth, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_param, NULL, NULL);
 
 /* Start of tfc_tpg_nacl_base_cit */
 
-CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group);
-
 static struct config_group *target_fabric_make_mappedlun(
        struct config_group *group,
        const char *name)
@@ -438,8 +393,6 @@ static void target_fabric_nacl_base_release(struct config_item *item)
 
 static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
        .release                = target_fabric_nacl_base_release,
-       .show_attribute         = target_fabric_nacl_base_attr_show,
-       .store_attribute        = target_fabric_nacl_base_attr_store,
 };
 
 static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
@@ -540,8 +493,6 @@ TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);
 
 /* Start of tfc_tpg_np_base_cit */
 
-CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group);
-
 static void target_fabric_np_base_release(struct config_item *item)
 {
        struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),
@@ -554,8 +505,6 @@ static void target_fabric_np_base_release(struct config_item *item)
 
 static struct configfs_item_operations target_fabric_np_base_item_ops = {
        .release                = target_fabric_np_base_release,
-       .show_attribute         = target_fabric_np_base_attr_show,
-       .store_attribute        = target_fabric_np_base_attr_store,
 };
 
 TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
@@ -610,132 +559,113 @@ TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);
 
 /* Start of tfc_tpg_port_cit */
 
-CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun);
-#define TCM_PORT_ATTR(_name, _mode)                                    \
-static struct target_fabric_port_attribute target_fabric_port_##_name =        \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_fabric_port_show_attr_##_name,                           \
-       target_fabric_port_store_attr_##_name);
-
-#define TCM_PORT_ATTOR_RO(_name)                                       \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_fabric_port_show_attr_##_name);
+static struct se_lun *item_to_lun(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_lun,
+                       lun_group);
+}
 
-/*
- * alua_tg_pt_gp
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
-       struct se_lun *lun,
-       char *page)
+static ssize_t target_fabric_port_alua_tg_pt_gp_show(struct config_item *item,
+               char *page)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_show_tg_pt_gp_info(lun, page);
 }
 
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
-       struct se_lun *lun,
-       const char *page,
-       size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_gp_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_store_tg_pt_gp_info(lun, page, count);
 }
 
-TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_offline
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
-       struct se_lun *lun,
-       char *page)
+static ssize_t target_fabric_port_alua_tg_pt_offline_show(
+               struct config_item *item, char *page)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_show_offline_bit(lun, page);
 }
 
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
-       struct se_lun *lun,
-       const char *page,
-       size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_offline_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_store_offline_bit(lun, page, count);
 }
 
-TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_status
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
-       struct se_lun *lun,
-       char *page)
+static ssize_t target_fabric_port_alua_tg_pt_status_show(
+               struct config_item *item, char *page)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_show_secondary_status(lun, page);
 }
 
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
-       struct se_lun *lun,
-       const char *page,
-       size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_status_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_store_secondary_status(lun, page, count);
 }
 
-TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR);
-
-/*
- * alua_tg_pt_write_md
- */
-static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
-       struct se_lun *lun,
-       char *page)
+static ssize_t target_fabric_port_alua_tg_pt_write_md_show(
+               struct config_item *item, char *page)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_show_secondary_write_metadata(lun, page);
 }
 
-static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
-       struct se_lun *lun,
-       const char *page,
-       size_t count)
+static ssize_t target_fabric_port_alua_tg_pt_write_md_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_lun *lun = item_to_lun(item);
+
        if (!lun || !lun->lun_se_dev)
                return -ENODEV;
 
        return core_alua_store_secondary_write_metadata(lun, page, count);
 }
 
-TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR);
-
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_gp);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_offline);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_status);
+CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_write_md);
 
 static struct configfs_attribute *target_fabric_port_attrs[] = {
-       &target_fabric_port_alua_tg_pt_gp.attr,
-       &target_fabric_port_alua_tg_pt_offline.attr,
-       &target_fabric_port_alua_tg_pt_status.attr,
-       &target_fabric_port_alua_tg_pt_write_md.attr,
+       &target_fabric_port_attr_alua_tg_pt_gp,
+       &target_fabric_port_attr_alua_tg_pt_offline,
+       &target_fabric_port_attr_alua_tg_pt_status,
+       &target_fabric_port_attr_alua_tg_pt_write_md,
        NULL,
 };
 
-CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group);
-
 static int target_fabric_port_link(
        struct config_item *lun_ci,
        struct config_item *se_dev_ci)
@@ -821,8 +751,6 @@ static void target_fabric_port_release(struct config_item *item)
 }
 
 static struct configfs_item_operations target_fabric_port_item_ops = {
-       .show_attribute         = target_fabric_port_attr_show,
-       .store_attribute        = target_fabric_port_attr_store,
        .release                = target_fabric_port_release,
        .allow_link             = target_fabric_port_link,
        .drop_link              = target_fabric_port_unlink,
@@ -952,50 +880,11 @@ TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
 
 /* End of tfc_tpg_lun_cit */
 
-/* Start of tfc_tpg_attrib_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group);
-
-static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
-       .show_attribute         = target_fabric_tpg_attrib_attr_show,
-       .store_attribute        = target_fabric_tpg_attrib_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL);
-
-/* End of tfc_tpg_attrib_cit */
-
-/* Start of tfc_tpg_auth_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_auth, se_portal_group, tpg_auth_group);
-
-static struct configfs_item_operations target_fabric_tpg_auth_item_ops = {
-       .show_attribute         = target_fabric_tpg_auth_attr_show,
-       .store_attribute        = target_fabric_tpg_auth_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL);
-
-/* End of tfc_tpg_attrib_cit */
-
-/* Start of tfc_tpg_param_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group);
-
-static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
-       .show_attribute         = target_fabric_tpg_param_attr_show,
-       .store_attribute        = target_fabric_tpg_param_attr_store,
-};
-
-TF_CIT_SETUP_DRV(tpg_param, &target_fabric_tpg_param_item_ops, NULL);
-
-/* End of tfc_tpg_param_cit */
+TF_CIT_SETUP_DRV(tpg_attrib, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_auth, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_param, NULL, NULL);
 
 /* Start of tfc_tpg_base_cit */
-/*
- * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO()
- */
-CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group);
 
 static void target_fabric_tpg_release(struct config_item *item)
 {
@@ -1009,8 +898,6 @@ static void target_fabric_tpg_release(struct config_item *item)
 
 static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
        .release                = target_fabric_tpg_release,
-       .show_attribute         = target_fabric_tpg_attr_show,
-       .store_attribute        = target_fabric_tpg_attr_store,
 };
 
 TF_CIT_SETUP_DRV(tpg_base, &target_fabric_tpg_base_item_ops, NULL);
@@ -1176,33 +1063,9 @@ static struct configfs_group_operations target_fabric_wwn_group_ops = {
        .make_group     = target_fabric_make_wwn,
        .drop_item      = target_fabric_drop_wwn,
 };
-/*
- * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO()
- */
-CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group);
-
-static struct configfs_item_operations target_fabric_wwn_item_ops = {
-       .show_attribute         = target_fabric_wwn_attr_show,
-       .store_attribute        = target_fabric_wwn_attr_store,
-};
-
-TF_CIT_SETUP_DRV(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops);
-
-/* End of tfc_wwn_cit */
-
-/* Start of tfc_discovery_cit */
-
-CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs,
-               tf_disc_group);
-
-static struct configfs_item_operations target_fabric_discovery_item_ops = {
-       .show_attribute         = target_fabric_discovery_attr_show,
-       .store_attribute        = target_fabric_discovery_attr_store,
-};
-
-TF_CIT_SETUP_DRV(discovery, &target_fabric_discovery_item_ops, NULL);
 
-/* End of tfc_discovery_cit */
+TF_CIT_SETUP_DRV(wwn, NULL, &target_fabric_wwn_group_ops);
+TF_CIT_SETUP_DRV(discovery, NULL, NULL);
 
 int target_fabric_setup_cits(struct target_fabric_configfs *tf)
 {
index 99c24acfe6761797fc9788f4f233d1c8c94a0e1d..dae0750c2032bd87430ab99609d475a615e691db 100644 (file)
@@ -87,6 +87,9 @@ void  target_free_device(struct se_device *);
 /* target_core_configfs.c */
 void   target_setup_backend_cits(struct target_backend *);
 
+/* target_core_fabric_configfs.c */
+int    target_fabric_setup_cits(struct target_fabric_configfs *);
+
 /* target_core_fabric_lib.c */
 int    target_get_pr_transport_id_len(struct se_node_acl *nacl,
                struct t10_pr_registration *pr_reg, int *format_code);
index 20ed5d2e151a6f50211273967e2cc107ba2b5bce..273c72b2b83dc016b2a317b778a8c391eebcb9c8 100644 (file)
@@ -37,7 +37,6 @@
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 #include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
 
 #include "target_core_internal.h"
 
  * SCSI Device Table
  */
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_dev, se_dev_stat_grps);
-#define DEV_STAT_SCSI_DEV_ATTR(_name, _mode)                           \
-static struct target_stat_scsi_dev_attribute                           \
-                       target_stat_scsi_dev_##_name =                  \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_dev_show_attr_##_name,                         \
-       target_stat_scsi_dev_store_attr_##_name);
-
-#define DEV_STAT_SCSI_DEV_ATTR_RO(_name)                               \
-static struct target_stat_scsi_dev_attribute                           \
-                       target_stat_scsi_dev_##_name =                  \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_dev_show_attr_##_name);
+static struct se_device *to_stat_dev(struct config_item *item)
+{
+       struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+                       struct se_dev_stat_grps, scsi_dev_group);
+       return container_of(sgrps, struct se_device, dev_stat_grps);
+}
 
-static ssize_t target_stat_scsi_dev_show_attr_inst(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_inst_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-       struct se_hba *hba = dev->se_hba;
+       struct se_hba *hba = to_stat_dev(item)->se_hba;
 
        return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
-DEV_STAT_SCSI_DEV_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_dev_show_attr_indx(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_indx_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+       return snprintf(page, PAGE_SIZE, "%u\n", to_stat_dev(item)->dev_index);
 }
-DEV_STAT_SCSI_DEV_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_dev_show_attr_role(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_role_show(struct config_item *item, char *page)
 {
        return snprintf(page, PAGE_SIZE, "Target\n");
 }
-DEV_STAT_SCSI_DEV_ATTR_RO(role);
 
-static ssize_t target_stat_scsi_dev_show_attr_ports(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_ports_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", dev->export_count);
+       return snprintf(page, PAGE_SIZE, "%u\n", to_stat_dev(item)->export_count);
 }
-DEV_STAT_SCSI_DEV_ATTR_RO(ports);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_dev, se_dev_stat_grps, scsi_dev_group);
+CONFIGFS_ATTR_RO(target_stat_, inst);
+CONFIGFS_ATTR_RO(target_stat_, indx);
+CONFIGFS_ATTR_RO(target_stat_, role);
+CONFIGFS_ATTR_RO(target_stat_, ports);
 
 static struct configfs_attribute *target_stat_scsi_dev_attrs[] = {
-       &target_stat_scsi_dev_inst.attr,
-       &target_stat_scsi_dev_indx.attr,
-       &target_stat_scsi_dev_role.attr,
-       &target_stat_scsi_dev_ports.attr,
+       &target_stat_attr_inst,
+       &target_stat_attr_indx,
+       &target_stat_attr_role,
+       &target_stat_attr_ports,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_dev_attrib_ops = {
-       .show_attribute         = target_stat_scsi_dev_attr_show,
-       .store_attribute        = target_stat_scsi_dev_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_dev_cit = {
-       .ct_item_ops            = &target_stat_scsi_dev_attrib_ops,
        .ct_attrs               = target_stat_scsi_dev_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -131,109 +104,78 @@ static struct config_item_type target_stat_scsi_dev_cit = {
 /*
  * SCSI Target Device Table
  */
+static struct se_device *to_stat_tgt_dev(struct config_item *item)
+{
+       struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+                       struct se_dev_stat_grps, scsi_tgt_dev_group);
+       return container_of(sgrps, struct se_device, dev_stat_grps);
+}
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_dev, se_dev_stat_grps);
-#define DEV_STAT_SCSI_TGT_DEV_ATTR(_name, _mode)                       \
-static struct target_stat_scsi_tgt_dev_attribute                       \
-                       target_stat_scsi_tgt_dev_##_name =              \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_tgt_dev_show_attr_##_name,                     \
-       target_stat_scsi_tgt_dev_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TGT_DEV_ATTR_RO(_name)                           \
-static struct target_stat_scsi_tgt_dev_attribute                       \
-                       target_stat_scsi_tgt_dev_##_name =              \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_tgt_dev_show_attr_##_name);
-
-static ssize_t target_stat_scsi_tgt_dev_show_attr_inst(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_inst_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-       struct se_hba *hba = dev->se_hba;
+       struct se_hba *hba = to_stat_tgt_dev(item)->se_hba;
 
        return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_tgt_dev_show_attr_indx(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_indx_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+       return snprintf(page, PAGE_SIZE, "%u\n", to_stat_tgt_dev(item)->dev_index);
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_tgt_dev_show_attr_num_lus(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_num_lus_show(struct config_item *item,
+               char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", LU_COUNT);
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(num_lus);
 
-static ssize_t target_stat_scsi_tgt_dev_show_attr_status(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_status_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
-       if (dev->export_count)
+       if (to_stat_tgt_dev(item)->export_count)
                return snprintf(page, PAGE_SIZE, "activated");
        else
                return snprintf(page, PAGE_SIZE, "deactivated");
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(status);
 
-static ssize_t target_stat_scsi_tgt_dev_show_attr_non_access_lus(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_non_access_lus_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
        int non_accessible_lus;
 
-       if (dev->export_count)
+       if (to_stat_tgt_dev(item)->export_count)
                non_accessible_lus = 0;
        else
                non_accessible_lus = 1;
 
        return snprintf(page, PAGE_SIZE, "%u\n", non_accessible_lus);
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(non_access_lus);
 
-static ssize_t target_stat_scsi_tgt_dev_show_attr_resets(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_tgt_resets_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
        return snprintf(page, PAGE_SIZE, "%lu\n",
-                       atomic_long_read(&dev->num_resets));
+                       atomic_long_read(&to_stat_tgt_dev(item)->num_resets));
 }
-DEV_STAT_SCSI_TGT_DEV_ATTR_RO(resets);
 
-
-CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_dev, se_dev_stat_grps, scsi_tgt_dev_group);
+CONFIGFS_ATTR_RO(target_stat_tgt_, inst);
+CONFIGFS_ATTR_RO(target_stat_tgt_, indx);
+CONFIGFS_ATTR_RO(target_stat_tgt_, num_lus);
+CONFIGFS_ATTR_RO(target_stat_tgt_, status);
+CONFIGFS_ATTR_RO(target_stat_tgt_, non_access_lus);
+CONFIGFS_ATTR_RO(target_stat_tgt_, resets);
 
 static struct configfs_attribute *target_stat_scsi_tgt_dev_attrs[] = {
-       &target_stat_scsi_tgt_dev_inst.attr,
-       &target_stat_scsi_tgt_dev_indx.attr,
-       &target_stat_scsi_tgt_dev_num_lus.attr,
-       &target_stat_scsi_tgt_dev_status.attr,
-       &target_stat_scsi_tgt_dev_non_access_lus.attr,
-       &target_stat_scsi_tgt_dev_resets.attr,
+       &target_stat_tgt_attr_inst,
+       &target_stat_tgt_attr_indx,
+       &target_stat_tgt_attr_num_lus,
+       &target_stat_tgt_attr_status,
+       &target_stat_tgt_attr_non_access_lus,
+       &target_stat_tgt_attr_resets,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_tgt_dev_attrib_ops = {
-       .show_attribute         = target_stat_scsi_tgt_dev_attr_show,
-       .store_attribute        = target_stat_scsi_tgt_dev_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_tgt_dev_cit = {
-       .ct_item_ops            = &target_stat_scsi_tgt_dev_attrib_ops,
        .ct_attrs               = target_stat_scsi_tgt_dev_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -242,72 +184,50 @@ static struct config_item_type target_stat_scsi_tgt_dev_cit = {
  * SCSI Logical Unit Table
  */
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_lu, se_dev_stat_grps);
-#define DEV_STAT_SCSI_LU_ATTR(_name, _mode)                            \
-static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_lu_show_attr_##_name,                          \
-       target_stat_scsi_lu_store_attr_##_name);
-
-#define DEV_STAT_SCSI_LU_ATTR_RO(_name)                                        \
-static struct target_stat_scsi_lu_attribute target_stat_scsi_lu_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_lu_show_attr_##_name);
+static struct se_device *to_stat_lu_dev(struct config_item *item)
+{
+       struct se_dev_stat_grps *sgrps = container_of(to_config_group(item),
+                       struct se_dev_stat_grps, scsi_lu_group);
+       return container_of(sgrps, struct se_device, dev_stat_grps);
+}
 
-static ssize_t target_stat_scsi_lu_show_attr_inst(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_inst_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-       struct se_hba *hba = dev->se_hba;
+       struct se_hba *hba = to_stat_lu_dev(item)->se_hba;
 
        return snprintf(page, PAGE_SIZE, "%u\n", hba->hba_index);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_lu_show_attr_dev(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_dev_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
-
-       return snprintf(page, PAGE_SIZE, "%u\n", dev->dev_index);
+       return snprintf(page, PAGE_SIZE, "%u\n",
+                       to_stat_lu_dev(item)->dev_index);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(dev);
 
-static ssize_t target_stat_scsi_lu_show_attr_indx(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_indx_show(struct config_item *item, char *page)
 {
        return snprintf(page, PAGE_SIZE, "%u\n", SCSI_LU_INDEX);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_lu_show_attr_lun(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_lun_show(struct config_item *item, char *page)
 {
        /* FIXME: scsiLuDefaultLun */
        return snprintf(page, PAGE_SIZE, "%llu\n", (unsigned long long)0);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(lun);
 
-static ssize_t target_stat_scsi_lu_show_attr_lu_name(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_lu_name_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuWwnName */
        return snprintf(page, PAGE_SIZE, "%s\n",
                        (strlen(dev->t10_wwn.unit_serial)) ?
                        dev->t10_wwn.unit_serial : "None");
 }
-DEV_STAT_SCSI_LU_ATTR_RO(lu_name);
 
-static ssize_t target_stat_scsi_lu_show_attr_vend(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_vend_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
        int i;
        char str[sizeof(dev->t10_wwn.vendor)+1];
 
@@ -318,13 +238,10 @@ static ssize_t target_stat_scsi_lu_show_attr_vend(
        str[i] = '\0';
        return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(vend);
 
-static ssize_t target_stat_scsi_lu_show_attr_prod(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_prod_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
        int i;
        char str[sizeof(dev->t10_wwn.model)+1];
 
@@ -335,13 +252,10 @@ static ssize_t target_stat_scsi_lu_show_attr_prod(
        str[i] = '\0';
        return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(prod);
 
-static ssize_t target_stat_scsi_lu_show_attr_rev(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_rev_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
        int i;
        char str[sizeof(dev->t10_wwn.revision)+1];
 
@@ -352,146 +266,137 @@ static ssize_t target_stat_scsi_lu_show_attr_rev(
        str[i] = '\0';
        return snprintf(page, PAGE_SIZE, "%s\n", str);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(rev);
 
-static ssize_t target_stat_scsi_lu_show_attr_dev_type(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_dev_type_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuPeripheralType */
        return snprintf(page, PAGE_SIZE, "%u\n",
                        dev->transport->get_device_type(dev));
 }
-DEV_STAT_SCSI_LU_ATTR_RO(dev_type);
 
-static ssize_t target_stat_scsi_lu_show_attr_status(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_status_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuStatus */
        return snprintf(page, PAGE_SIZE, "%s\n",
                (dev->export_count) ? "available" : "notavailable");
 }
-DEV_STAT_SCSI_LU_ATTR_RO(status);
 
-static ssize_t target_stat_scsi_lu_show_attr_state_bit(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_state_bit_show(struct config_item *item,
+               char *page)
 {
        /* scsiLuState */
        return snprintf(page, PAGE_SIZE, "exposed\n");
 }
-DEV_STAT_SCSI_LU_ATTR_RO(state_bit);
 
-static ssize_t target_stat_scsi_lu_show_attr_num_cmds(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_num_cmds_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuNumCommands */
        return snprintf(page, PAGE_SIZE, "%lu\n",
                        atomic_long_read(&dev->num_cmds));
 }
-DEV_STAT_SCSI_LU_ATTR_RO(num_cmds);
 
-static ssize_t target_stat_scsi_lu_show_attr_read_mbytes(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_read_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuReadMegaBytes */
        return snprintf(page, PAGE_SIZE, "%lu\n",
                        atomic_long_read(&dev->read_bytes) >> 20);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(read_mbytes);
 
-static ssize_t target_stat_scsi_lu_show_attr_write_mbytes(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_write_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuWrittenMegaBytes */
        return snprintf(page, PAGE_SIZE, "%lu\n",
                        atomic_long_read(&dev->write_bytes) >> 20);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(write_mbytes);
 
-static ssize_t target_stat_scsi_lu_show_attr_resets(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_resets_show(struct config_item *item, char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuInResets */
-       return snprintf(page, PAGE_SIZE, "%lu\n", atomic_long_read(&dev->num_resets));
+       return snprintf(page, PAGE_SIZE, "%lu\n",
+               atomic_long_read(&dev->num_resets));
 }
-DEV_STAT_SCSI_LU_ATTR_RO(resets);
 
-static ssize_t target_stat_scsi_lu_show_attr_full_stat(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_full_stat_show(struct config_item *item,
+               char *page)
 {
        /* FIXME: scsiLuOutTaskSetFullStatus */
        return snprintf(page, PAGE_SIZE, "%u\n", 0);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(full_stat);
 
-static ssize_t target_stat_scsi_lu_show_attr_hs_num_cmds(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_hs_num_cmds_show(struct config_item *item,
+               char *page)
 {
        /* FIXME: scsiLuHSInCommands */
        return snprintf(page, PAGE_SIZE, "%u\n", 0);
 }
-DEV_STAT_SCSI_LU_ATTR_RO(hs_num_cmds);
 
-static ssize_t target_stat_scsi_lu_show_attr_creation_time(
-       struct se_dev_stat_grps *sgrps, char *page)
+static ssize_t target_stat_lu_creation_time_show(struct config_item *item,
+               char *page)
 {
-       struct se_device *dev =
-               container_of(sgrps, struct se_device, dev_stat_grps);
+       struct se_device *dev = to_stat_lu_dev(item);
 
        /* scsiLuCreationTime */
        return snprintf(page, PAGE_SIZE, "%u\n", (u32)(((u32)dev->creation_time -
                                INITIAL_JIFFIES) * 100 / HZ));
 }
-DEV_STAT_SCSI_LU_ATTR_RO(creation_time);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_lu, se_dev_stat_grps, scsi_lu_group);
+CONFIGFS_ATTR_RO(target_stat_lu_, inst);
+CONFIGFS_ATTR_RO(target_stat_lu_, dev);
+CONFIGFS_ATTR_RO(target_stat_lu_, indx);
+CONFIGFS_ATTR_RO(target_stat_lu_, lun);
+CONFIGFS_ATTR_RO(target_stat_lu_, lu_name);
+CONFIGFS_ATTR_RO(target_stat_lu_, vend);
+CONFIGFS_ATTR_RO(target_stat_lu_, prod);
+CONFIGFS_ATTR_RO(target_stat_lu_, rev);
+CONFIGFS_ATTR_RO(target_stat_lu_, dev_type);
+CONFIGFS_ATTR_RO(target_stat_lu_, status);
+CONFIGFS_ATTR_RO(target_stat_lu_, state_bit);
+CONFIGFS_ATTR_RO(target_stat_lu_, num_cmds);
+CONFIGFS_ATTR_RO(target_stat_lu_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_lu_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_lu_, resets);
+CONFIGFS_ATTR_RO(target_stat_lu_, full_stat);
+CONFIGFS_ATTR_RO(target_stat_lu_, hs_num_cmds);
+CONFIGFS_ATTR_RO(target_stat_lu_, creation_time);
 
 static struct configfs_attribute *target_stat_scsi_lu_attrs[] = {
-       &target_stat_scsi_lu_inst.attr,
-       &target_stat_scsi_lu_dev.attr,
-       &target_stat_scsi_lu_indx.attr,
-       &target_stat_scsi_lu_lun.attr,
-       &target_stat_scsi_lu_lu_name.attr,
-       &target_stat_scsi_lu_vend.attr,
-       &target_stat_scsi_lu_prod.attr,
-       &target_stat_scsi_lu_rev.attr,
-       &target_stat_scsi_lu_dev_type.attr,
-       &target_stat_scsi_lu_status.attr,
-       &target_stat_scsi_lu_state_bit.attr,
-       &target_stat_scsi_lu_num_cmds.attr,
-       &target_stat_scsi_lu_read_mbytes.attr,
-       &target_stat_scsi_lu_write_mbytes.attr,
-       &target_stat_scsi_lu_resets.attr,
-       &target_stat_scsi_lu_full_stat.attr,
-       &target_stat_scsi_lu_hs_num_cmds.attr,
-       &target_stat_scsi_lu_creation_time.attr,
+       &target_stat_lu_attr_inst,
+       &target_stat_lu_attr_dev,
+       &target_stat_lu_attr_indx,
+       &target_stat_lu_attr_lun,
+       &target_stat_lu_attr_lu_name,
+       &target_stat_lu_attr_vend,
+       &target_stat_lu_attr_prod,
+       &target_stat_lu_attr_rev,
+       &target_stat_lu_attr_dev_type,
+       &target_stat_lu_attr_status,
+       &target_stat_lu_attr_state_bit,
+       &target_stat_lu_attr_num_cmds,
+       &target_stat_lu_attr_read_mbytes,
+       &target_stat_lu_attr_write_mbytes,
+       &target_stat_lu_attr_resets,
+       &target_stat_lu_attr_full_stat,
+       &target_stat_lu_attr_hs_num_cmds,
+       &target_stat_lu_attr_creation_time,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_lu_attrib_ops = {
-       .show_attribute         = target_stat_scsi_lu_attr_show,
-       .store_attribute        = target_stat_scsi_lu_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_lu_cit = {
-       .ct_item_ops            = &target_stat_scsi_lu_attrib_ops,
        .ct_attrs               = target_stat_scsi_lu_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -521,24 +426,16 @@ void target_stat_setup_dev_default_groups(struct se_device *dev)
  * SCSI Port Table
  */
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_port, se_port_stat_grps);
-#define DEV_STAT_SCSI_PORT_ATTR(_name, _mode)                          \
-static struct target_stat_scsi_port_attribute                          \
-                       target_stat_scsi_port_##_name =                 \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_port_show_attr_##_name,                        \
-       target_stat_scsi_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_PORT_ATTR_RO(_name)                              \
-static struct target_stat_scsi_port_attribute                          \
-                       target_stat_scsi_port_##_name =                 \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_port_show_attr_##_name);
+static struct se_lun *to_stat_port(struct config_item *item)
+{
+       struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+                       struct se_port_stat_grps, scsi_port_group);
+       return container_of(pgrps, struct se_lun, port_stat_grps);
+}
 
-static ssize_t target_stat_scsi_port_show_attr_inst(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_inst_show(struct config_item *item, char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -549,12 +446,10 @@ static ssize_t target_stat_scsi_port_show_attr_inst(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_PORT_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_port_show_attr_dev(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_dev_show(struct config_item *item, char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -565,12 +460,10 @@ static ssize_t target_stat_scsi_port_show_attr_dev(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_PORT_ATTR_RO(dev);
 
-static ssize_t target_stat_scsi_port_show_attr_indx(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_indx_show(struct config_item *item, char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -581,12 +474,10 @@ static ssize_t target_stat_scsi_port_show_attr_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_PORT_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_port_show_attr_role(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_role_show(struct config_item *item, char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -597,12 +488,11 @@ static ssize_t target_stat_scsi_port_show_attr_role(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_PORT_ATTR_RO(role);
 
-static ssize_t target_stat_scsi_port_show_attr_busy_count(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_port_busy_count_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -615,26 +505,23 @@ static ssize_t target_stat_scsi_port_show_attr_busy_count(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_PORT_ATTR_RO(busy_count);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_port, se_port_stat_grps, scsi_port_group);
+CONFIGFS_ATTR_RO(target_stat_port_, inst);
+CONFIGFS_ATTR_RO(target_stat_port_, dev);
+CONFIGFS_ATTR_RO(target_stat_port_, indx);
+CONFIGFS_ATTR_RO(target_stat_port_, role);
+CONFIGFS_ATTR_RO(target_stat_port_, busy_count);
 
 static struct configfs_attribute *target_stat_scsi_port_attrs[] = {
-       &target_stat_scsi_port_inst.attr,
-       &target_stat_scsi_port_dev.attr,
-       &target_stat_scsi_port_indx.attr,
-       &target_stat_scsi_port_role.attr,
-       &target_stat_scsi_port_busy_count.attr,
+       &target_stat_port_attr_inst,
+       &target_stat_port_attr_dev,
+       &target_stat_port_attr_indx,
+       &target_stat_port_attr_role,
+       &target_stat_port_attr_busy_count,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_port_attrib_ops = {
-       .show_attribute         = target_stat_scsi_port_attr_show,
-       .store_attribute        = target_stat_scsi_port_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_port_cit = {
-       .ct_item_ops            = &target_stat_scsi_port_attrib_ops,
        .ct_attrs               = target_stat_scsi_port_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -642,24 +529,17 @@ static struct config_item_type target_stat_scsi_port_cit = {
 /*
  * SCSI Target Port Table
  */
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_tgt_port, se_port_stat_grps);
-#define DEV_STAT_SCSI_TGT_PORT_ATTR(_name, _mode)                      \
-static struct target_stat_scsi_tgt_port_attribute                      \
-                       target_stat_scsi_tgt_port_##_name =             \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_tgt_port_show_attr_##_name,                    \
-       target_stat_scsi_tgt_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TGT_PORT_ATTR_RO(_name)                          \
-static struct target_stat_scsi_tgt_port_attribute                      \
-                       target_stat_scsi_tgt_port_##_name =             \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_tgt_port_show_attr_##_name);
-
-static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
-       struct se_port_stat_grps *pgrps, char *page)
-{
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+static struct se_lun *to_stat_tgt_port(struct config_item *item)
+{
+       struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+                       struct se_port_stat_grps, scsi_tgt_port_group);
+       return container_of(pgrps, struct se_lun, port_stat_grps);
+}
+
+static ssize_t target_stat_tgt_port_inst_show(struct config_item *item,
+               char *page)
+{
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -670,12 +550,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_inst(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_dev_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -686,12 +565,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_dev(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(dev);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -702,12 +580,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_name(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_name_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_portal_group *tpg = lun->lun_tpg;
        struct se_device *dev;
        ssize_t ret = -ENODEV;
@@ -721,12 +598,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_name(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(name);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_port_index_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_portal_group *tpg = lun->lun_tpg;
        struct se_device *dev;
        ssize_t ret = -ENODEV;
@@ -740,12 +616,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_port_index(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(port_index);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_in_cmds_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -757,12 +632,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_in_cmds(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(in_cmds);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_write_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -774,12 +648,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_write_mbytes(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(write_mbytes);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_read_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -791,12 +664,11 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_read_mbytes(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(read_mbytes);
 
-static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_tgt_port_hs_in_cmds_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_stat_tgt_port(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -809,57 +681,49 @@ static ssize_t target_stat_scsi_tgt_port_show_attr_hs_in_cmds(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TGT_PORT_ATTR_RO(hs_in_cmds);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_tgt_port, se_port_stat_grps,
-               scsi_tgt_port_group);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, inst);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, dev);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, indx);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, name);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, port_index);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, in_cmds);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_tgt_port_, hs_in_cmds);
 
 static struct configfs_attribute *target_stat_scsi_tgt_port_attrs[] = {
-       &target_stat_scsi_tgt_port_inst.attr,
-       &target_stat_scsi_tgt_port_dev.attr,
-       &target_stat_scsi_tgt_port_indx.attr,
-       &target_stat_scsi_tgt_port_name.attr,
-       &target_stat_scsi_tgt_port_port_index.attr,
-       &target_stat_scsi_tgt_port_in_cmds.attr,
-       &target_stat_scsi_tgt_port_write_mbytes.attr,
-       &target_stat_scsi_tgt_port_read_mbytes.attr,
-       &target_stat_scsi_tgt_port_hs_in_cmds.attr,
+       &target_stat_tgt_port_attr_inst,
+       &target_stat_tgt_port_attr_dev,
+       &target_stat_tgt_port_attr_indx,
+       &target_stat_tgt_port_attr_name,
+       &target_stat_tgt_port_attr_port_index,
+       &target_stat_tgt_port_attr_in_cmds,
+       &target_stat_tgt_port_attr_write_mbytes,
+       &target_stat_tgt_port_attr_read_mbytes,
+       &target_stat_tgt_port_attr_hs_in_cmds,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_tgt_port_attrib_ops = {
-       .show_attribute         = target_stat_scsi_tgt_port_attr_show,
-       .store_attribute        = target_stat_scsi_tgt_port_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_tgt_port_cit = {
-       .ct_item_ops            = &target_stat_scsi_tgt_port_attrib_ops,
        .ct_attrs               = target_stat_scsi_tgt_port_attrs,
        .ct_owner               = THIS_MODULE,
 };
 
 /*
  * SCSI Transport Table
-o */
-
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_transport, se_port_stat_grps);
-#define DEV_STAT_SCSI_TRANSPORT_ATTR(_name, _mode)                     \
-static struct target_stat_scsi_transport_attribute                     \
-                       target_stat_scsi_transport_##_name =            \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_transport_show_attr_##_name,                   \
-       target_stat_scsi_transport_store_attr_##_name);
-
-#define DEV_STAT_SCSI_TRANSPORT_ATTR_RO(_name)                         \
-static struct target_stat_scsi_transport_attribute                     \
-                       target_stat_scsi_transport_##_name =            \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_transport_show_attr_##_name);
-
-static ssize_t target_stat_scsi_transport_show_attr_inst(
-       struct se_port_stat_grps *pgrps, char *page)
-{
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+ */
+static struct se_lun *to_transport_stat(struct config_item *item)
+{
+       struct se_port_stat_grps *pgrps = container_of(to_config_group(item),
+                       struct se_port_stat_grps, scsi_transport_group);
+       return container_of(pgrps, struct se_lun, port_stat_grps);
+}
+
+static ssize_t target_stat_transport_inst_show(struct config_item *item,
+               char *page)
+{
+       struct se_lun *lun = to_transport_stat(item);
        struct se_device *dev;
        ssize_t ret = -ENODEV;
 
@@ -870,12 +734,11 @@ static ssize_t target_stat_scsi_transport_show_attr_inst(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_transport_show_attr_device(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_device_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_transport_stat(item);
        struct se_device *dev;
        struct se_portal_group *tpg = lun->lun_tpg;
        ssize_t ret = -ENODEV;
@@ -890,12 +753,11 @@ static ssize_t target_stat_scsi_transport_show_attr_device(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(device);
 
-static ssize_t target_stat_scsi_transport_show_attr_indx(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_transport_stat(item);
        struct se_device *dev;
        struct se_portal_group *tpg = lun->lun_tpg;
        ssize_t ret = -ENODEV;
@@ -908,12 +770,11 @@ static ssize_t target_stat_scsi_transport_show_attr_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_transport_show_attr_dev_name(
-       struct se_port_stat_grps *pgrps, char *page)
+static ssize_t target_stat_transport_dev_name_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun *lun = container_of(pgrps, struct se_lun, port_stat_grps);
+       struct se_lun *lun = to_transport_stat(item);
        struct se_device *dev;
        struct se_portal_group *tpg = lun->lun_tpg;
        struct t10_wwn *wwn;
@@ -932,26 +793,21 @@ static ssize_t target_stat_scsi_transport_show_attr_dev_name(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_TRANSPORT_ATTR_RO(dev_name);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_transport, se_port_stat_grps,
-               scsi_transport_group);
+CONFIGFS_ATTR_RO(target_stat_transport_, inst);
+CONFIGFS_ATTR_RO(target_stat_transport_, device);
+CONFIGFS_ATTR_RO(target_stat_transport_, indx);
+CONFIGFS_ATTR_RO(target_stat_transport_, dev_name);
 
 static struct configfs_attribute *target_stat_scsi_transport_attrs[] = {
-       &target_stat_scsi_transport_inst.attr,
-       &target_stat_scsi_transport_device.attr,
-       &target_stat_scsi_transport_indx.attr,
-       &target_stat_scsi_transport_dev_name.attr,
+       &target_stat_transport_attr_inst,
+       &target_stat_transport_attr_device,
+       &target_stat_transport_attr_indx,
+       &target_stat_transport_attr_dev_name,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_transport_attrib_ops = {
-       .show_attribute         = target_stat_scsi_transport_attr_show,
-       .store_attribute        = target_stat_scsi_transport_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_transport_cit = {
-       .ct_item_ops            = &target_stat_scsi_transport_attrib_ops,
        .ct_attrs               = target_stat_scsi_transport_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -981,25 +837,17 @@ void target_stat_setup_port_default_groups(struct se_lun *lun)
  * SCSI Authorized Initiator Table
  */
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_auth_intr, se_ml_stat_grps);
-#define DEV_STAT_SCSI_AUTH_INTR_ATTR(_name, _mode)                     \
-static struct target_stat_scsi_auth_intr_attribute                     \
-                       target_stat_scsi_auth_intr_##_name =            \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_auth_intr_show_attr_##_name,                   \
-       target_stat_scsi_auth_intr_store_attr_##_name);
-
-#define DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(_name)                         \
-static struct target_stat_scsi_auth_intr_attribute                     \
-                       target_stat_scsi_auth_intr_##_name =            \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_auth_intr_show_attr_##_name);
-
-static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
-       struct se_ml_stat_grps *lgrps, char *page)
-{
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+static struct se_lun_acl *auth_to_lacl(struct config_item *item)
+{
+       struct se_ml_stat_grps *lgrps = container_of(to_config_group(item),
+                       struct se_ml_stat_grps, scsi_auth_intr_group);
+       return container_of(lgrps, struct se_lun_acl, ml_stat_grps);
+}
+
+static ssize_t target_stat_auth_inst_show(struct config_item *item,
+               char *page)
+{
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_portal_group *tpg;
@@ -1018,13 +866,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_inst(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_dev_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_lun *lun;
@@ -1042,13 +888,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_port(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_port_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_portal_group *tpg;
@@ -1066,13 +910,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_port(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(port);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1088,13 +930,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_dev_or_port_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1110,13 +950,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_dev_or_port(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(dev_or_port);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_intr_name_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1132,13 +970,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_intr_name(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(intr_name);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_map_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1154,13 +990,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_map_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(map_indx);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_att_count_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1176,13 +1010,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_att_count(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(att_count);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_num_cmds_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1199,13 +1031,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_num_cmds(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(num_cmds);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_read_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1222,13 +1052,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_read_mbytes(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(read_mbytes);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_write_mbytes_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1245,13 +1073,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_write_mbytes(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(write_mbytes);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_hs_num_cmds_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1267,13 +1093,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_hs_num_cmds(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(hs_num_cmds);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_creation_time_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1290,13 +1114,11 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_creation_time(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(creation_time);
 
-static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_auth_row_status_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = auth_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1312,36 +1134,41 @@ static ssize_t target_stat_scsi_auth_intr_show_attr_row_status(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_AUTH_INTR_ATTR_RO(row_status);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_auth_intr, se_ml_stat_grps,
-               scsi_auth_intr_group);
+CONFIGFS_ATTR_RO(target_stat_auth_, inst);
+CONFIGFS_ATTR_RO(target_stat_auth_, dev);
+CONFIGFS_ATTR_RO(target_stat_auth_, port);
+CONFIGFS_ATTR_RO(target_stat_auth_, indx);
+CONFIGFS_ATTR_RO(target_stat_auth_, dev_or_port);
+CONFIGFS_ATTR_RO(target_stat_auth_, intr_name);
+CONFIGFS_ATTR_RO(target_stat_auth_, map_indx);
+CONFIGFS_ATTR_RO(target_stat_auth_, att_count);
+CONFIGFS_ATTR_RO(target_stat_auth_, num_cmds);
+CONFIGFS_ATTR_RO(target_stat_auth_, read_mbytes);
+CONFIGFS_ATTR_RO(target_stat_auth_, write_mbytes);
+CONFIGFS_ATTR_RO(target_stat_auth_, hs_num_cmds);
+CONFIGFS_ATTR_RO(target_stat_auth_, creation_time);
+CONFIGFS_ATTR_RO(target_stat_auth_, row_status);
 
 static struct configfs_attribute *target_stat_scsi_auth_intr_attrs[] = {
-       &target_stat_scsi_auth_intr_inst.attr,
-       &target_stat_scsi_auth_intr_dev.attr,
-       &target_stat_scsi_auth_intr_port.attr,
-       &target_stat_scsi_auth_intr_indx.attr,
-       &target_stat_scsi_auth_intr_dev_or_port.attr,
-       &target_stat_scsi_auth_intr_intr_name.attr,
-       &target_stat_scsi_auth_intr_map_indx.attr,
-       &target_stat_scsi_auth_intr_att_count.attr,
-       &target_stat_scsi_auth_intr_num_cmds.attr,
-       &target_stat_scsi_auth_intr_read_mbytes.attr,
-       &target_stat_scsi_auth_intr_write_mbytes.attr,
-       &target_stat_scsi_auth_intr_hs_num_cmds.attr,
-       &target_stat_scsi_auth_intr_creation_time.attr,
-       &target_stat_scsi_auth_intr_row_status.attr,
+       &target_stat_auth_attr_inst,
+       &target_stat_auth_attr_dev,
+       &target_stat_auth_attr_port,
+       &target_stat_auth_attr_indx,
+       &target_stat_auth_attr_dev_or_port,
+       &target_stat_auth_attr_intr_name,
+       &target_stat_auth_attr_map_indx,
+       &target_stat_auth_attr_att_count,
+       &target_stat_auth_attr_num_cmds,
+       &target_stat_auth_attr_read_mbytes,
+       &target_stat_auth_attr_write_mbytes,
+       &target_stat_auth_attr_hs_num_cmds,
+       &target_stat_auth_attr_creation_time,
+       &target_stat_auth_attr_row_status,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_auth_intr_attrib_ops = {
-       .show_attribute         = target_stat_scsi_auth_intr_attr_show,
-       .store_attribute        = target_stat_scsi_auth_intr_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_auth_intr_cit = {
-       .ct_item_ops            = &target_stat_scsi_auth_intr_attrib_ops,
        .ct_attrs               = target_stat_scsi_auth_intr_attrs,
        .ct_owner               = THIS_MODULE,
 };
@@ -1350,25 +1177,17 @@ static struct config_item_type target_stat_scsi_auth_intr_cit = {
  * SCSI Attached Initiator Port Table
  */
 
-CONFIGFS_EATTR_STRUCT(target_stat_scsi_att_intr_port, se_ml_stat_grps);
-#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR(_name, _mode)                        \
-static struct target_stat_scsi_att_intr_port_attribute                 \
-               target_stat_scsi_att_intr_port_##_name =                \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       target_stat_scsi_att_intr_port_show_attr_##_name,               \
-       target_stat_scsi_att_intr_port_store_attr_##_name);
-
-#define DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(_name)                    \
-static struct target_stat_scsi_att_intr_port_attribute                 \
-               target_stat_scsi_att_intr_port_##_name =                \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       target_stat_scsi_att_intr_port_show_attr_##_name);
-
-static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
-       struct se_ml_stat_grps *lgrps, char *page)
-{
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+static struct se_lun_acl *iport_to_lacl(struct config_item *item)
+{
+       struct se_ml_stat_grps *lgrps = container_of(to_config_group(item),
+                       struct se_ml_stat_grps, scsi_att_intr_port_group);
+       return container_of(lgrps, struct se_lun_acl, ml_stat_grps);
+}
+
+static ssize_t target_stat_iport_inst_show(struct config_item *item,
+               char *page)
+{
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_portal_group *tpg;
@@ -1387,13 +1206,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_inst(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(inst);
 
-static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_dev_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_lun *lun;
@@ -1411,13 +1228,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_dev(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(dev);
 
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        struct se_portal_group *tpg;
@@ -1435,13 +1250,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port);
 
-static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_session *se_sess;
        struct se_portal_group *tpg;
@@ -1461,13 +1274,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_indx(
        spin_unlock_irq(&nacl->nacl_sess_lock);
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(indx);
 
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_auth_indx_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_dev_entry *deve;
        ssize_t ret;
@@ -1483,13 +1294,11 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_auth_indx(
        rcu_read_unlock();
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_auth_indx);
 
-static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
-       struct se_ml_stat_grps *lgrps, char *page)
+static ssize_t target_stat_iport_port_ident_show(struct config_item *item,
+               char *page)
 {
-       struct se_lun_acl *lacl = container_of(lgrps,
-                       struct se_lun_acl, ml_stat_grps);
+       struct se_lun_acl *lacl = iport_to_lacl(item);
        struct se_node_acl *nacl = lacl->se_lun_nacl;
        struct se_session *se_sess;
        struct se_portal_group *tpg;
@@ -1513,28 +1322,25 @@ static ssize_t target_stat_scsi_att_intr_port_show_attr_port_ident(
        spin_unlock_irq(&nacl->nacl_sess_lock);
        return ret;
 }
-DEV_STAT_SCSI_ATTR_INTR_PORT_ATTR_RO(port_ident);
 
-CONFIGFS_EATTR_OPS(target_stat_scsi_att_intr_port, se_ml_stat_grps,
-               scsi_att_intr_port_group);
+CONFIGFS_ATTR_RO(target_stat_iport_, inst);
+CONFIGFS_ATTR_RO(target_stat_iport_, dev);
+CONFIGFS_ATTR_RO(target_stat_iport_, port);
+CONFIGFS_ATTR_RO(target_stat_iport_, indx);
+CONFIGFS_ATTR_RO(target_stat_iport_, port_auth_indx);
+CONFIGFS_ATTR_RO(target_stat_iport_, port_ident);
 
 static struct configfs_attribute *target_stat_scsi_ath_intr_port_attrs[] = {
-       &target_stat_scsi_att_intr_port_inst.attr,
-       &target_stat_scsi_att_intr_port_dev.attr,
-       &target_stat_scsi_att_intr_port_port.attr,
-       &target_stat_scsi_att_intr_port_indx.attr,
-       &target_stat_scsi_att_intr_port_port_auth_indx.attr,
-       &target_stat_scsi_att_intr_port_port_ident.attr,
+       &target_stat_iport_attr_inst,
+       &target_stat_iport_attr_dev,
+       &target_stat_iport_attr_port,
+       &target_stat_iport_attr_indx,
+       &target_stat_iport_attr_port_auth_indx,
+       &target_stat_iport_attr_port_ident,
        NULL,
 };
 
-static struct configfs_item_operations target_stat_scsi_att_intr_port_attrib_ops = {
-       .show_attribute         = target_stat_scsi_att_intr_port_attr_show,
-       .store_attribute        = target_stat_scsi_att_intr_port_attr_store,
-};
-
 static struct config_item_type target_stat_scsi_att_intr_port_cit = {
-       .ct_item_ops            = &target_stat_scsi_att_intr_port_attrib_ops,
        .ct_attrs               = target_stat_scsi_ath_intr_port_attrs,
        .ct_owner               = THIS_MODULE,
 };
index aa3caca8bace13dc29a8cd9cb01d5b252b5c8a6c..064d6dfb5b6d9391bdd96f55ec4ae3f7d238655b 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
 
index 16670933013bf6b7d803471a73de3c87b79459a1..85aeaa0ad303b9cff6e33234c2fe685b964ca53b 100644 (file)
@@ -38,8 +38,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
 
@@ -131,55 +129,51 @@ static ssize_t ft_wwn_store(void *arg, const char *buf, size_t len)
  * ACL auth ops.
  */
 
-static ssize_t ft_nacl_show_port_name(
-       struct se_node_acl *se_nacl,
-       char *page)
+static ssize_t ft_nacl_port_name_show(struct config_item *item, char *page)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct ft_node_acl *acl = container_of(se_nacl,
                        struct ft_node_acl, se_node_acl);
 
        return ft_wwn_show(&acl->node_auth.port_name, page);
 }
 
-static ssize_t ft_nacl_store_port_name(
-       struct se_node_acl *se_nacl,
-       const char *page,
-       size_t count)
+static ssize_t ft_nacl_port_name_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct ft_node_acl *acl = container_of(se_nacl,
                        struct ft_node_acl, se_node_acl);
 
        return ft_wwn_store(&acl->node_auth.port_name, page, count);
 }
 
-TF_NACL_BASE_ATTR(ft, port_name, S_IRUGO | S_IWUSR);
-
-static ssize_t ft_nacl_show_node_name(
-       struct se_node_acl *se_nacl,
-       char *page)
+static ssize_t ft_nacl_node_name_show(struct config_item *item,
+               char *page)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct ft_node_acl *acl = container_of(se_nacl,
                        struct ft_node_acl, se_node_acl);
 
        return ft_wwn_show(&acl->node_auth.node_name, page);
 }
 
-static ssize_t ft_nacl_store_node_name(
-       struct se_node_acl *se_nacl,
-       const char *page,
-       size_t count)
+static ssize_t ft_nacl_node_name_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_node_acl *se_nacl = acl_to_nacl(item);
        struct ft_node_acl *acl = container_of(se_nacl,
                        struct ft_node_acl, se_node_acl);
 
        return ft_wwn_store(&acl->node_auth.node_name, page, count);
 }
 
-TF_NACL_BASE_ATTR(ft, node_name, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(ft_nacl_, node_name);
+CONFIGFS_ATTR(ft_nacl_, port_name);
 
 static struct configfs_attribute *ft_nacl_base_attrs[] = {
-       &ft_nacl_port_name.attr,
-       &ft_nacl_node_name.attr,
+       &ft_nacl_attr_port_name,
+       &ft_nacl_attr_node_name,
        NULL,
 };
 
@@ -386,18 +380,16 @@ static void ft_del_wwn(struct se_wwn *wwn)
        kfree(ft_wwn);
 }
 
-static ssize_t ft_wwn_show_attr_version(
-       struct target_fabric_configfs *tf,
-       char *page)
+static ssize_t ft_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "TCM FC " FT_VERSION " on %s/%s on "
                ""UTS_RELEASE"\n",  utsname()->sysname, utsname()->machine);
 }
 
-TF_WWN_ATTR_RO(ft, version);
+CONFIGFS_ATTR_RO(ft_wwn_, version);
 
 static struct configfs_attribute *ft_wwn_attrs[] = {
-       &ft_wwn_version.attr,
+       &ft_wwn_attr_version,
        NULL,
 };
 
index 4b0fedd6bd4be2236f2beb636e05251345687c60..847c1aa6fbf4d037bb385041719b39f1ef2c37b6 100644 (file)
@@ -44,7 +44,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
 
index 31a9e3fb98c5321de2e6b774c875845638c81862..7b934eac995df68aaf764bceaaa4f14472db3314 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/configfs_macros.h>
 
 #include "tcm_fc.h"
 
index 13844261cd5f3cdad44131a3e215f97d2ecae2f4..ed776149261ea1022fc0586ce3be200967ec4c0b 100644 (file)
@@ -169,7 +169,7 @@ static inline int tty_copy_to_user(struct tty_struct *tty,
 {
        struct n_tty_data *ldata = tty->disc_data;
 
-       tty_audit_add_data(tty, to, n, ldata->icanon);
+       tty_audit_add_data(tty, from, n, ldata->icanon);
        return copy_to_user(to, from, n);
 }
 
index c0533a57ec539f60768bdbed0aa49e929aaa16bd..910bfee5a88b7f07f5a4c00aad47a45361a1d19b 100644 (file)
@@ -60,3 +60,4 @@ int fsl8250_handle_irq(struct uart_port *port)
        spin_unlock_irqrestore(&up->port.lock, flags);
        return 1;
 }
+EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
index e6f5e12a2d83bcc5c03b3e2b81caf50f70721467..6412f1455beb3622f27e1738a468ff93d00fedfc 100644 (file)
@@ -373,6 +373,7 @@ config SERIAL_8250_MID
        depends on SERIAL_8250 && PCI
        select HSU_DMA if SERIAL_8250_DMA
        select HSU_DMA_PCI if X86_INTEL_MID
+       select RATIONAL
        help
          Selecting this option will enable handling of the extra features
          present on the UART found on Intel Medfield SOC and various other
index 1aec4404062d8f1995e8da8da821a1b176cb0e7a..f38beb28e7ae60e87316754b555ba08e2e77a3ac 100644 (file)
@@ -1539,7 +1539,6 @@ config SERIAL_FSL_LPUART
        tristate "Freescale lpuart serial port support"
        depends on HAS_DMA
        select SERIAL_CORE
-       select SERIAL_EARLYCON
        help
          Support for the on-chip lpuart on some Freescale SOCs.
 
@@ -1547,6 +1546,7 @@ config SERIAL_FSL_LPUART_CONSOLE
        bool "Console on Freescale lpuart serial port"
        depends on SERIAL_FSL_LPUART=y
        select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
        help
          If you have enabled the lpuart serial port on the Freescale SoCs,
          you can make it the console by answering Y to this option.
index 681e0f3d5e0ef895b0f618a24a40cf138f8f0eca..a1c0a89d9c7f3cfcfd994477e7e7e69aa1755d04 100644 (file)
@@ -474,7 +474,7 @@ static int bcm_uart_startup(struct uart_port *port)
 
        /* register irq and enable rx interrupts */
        ret = request_irq(port->irq, bcm_uart_interrupt, 0,
-                         bcm_uart_type(port), port);
+                         dev_name(port->dev), port);
        if (ret)
                return ret;
        bcm_uart_writel(port, UART_RX_INT_MASK, UART_IR_REG);
index 6813e316e9ff3d3e58fb2c68d582a3a285295aa3..2f80bc7e44fb3c4f16210a806c0fcaecee3e3b1c 100644 (file)
@@ -894,7 +894,7 @@ static int etraxfs_uart_probe(struct platform_device *pdev)
        up->regi_ser = of_iomap(np, 0);
        up->port.dev = &pdev->dev;
 
-       up->gpios = mctrl_gpio_init(&pdev->dev, 0);
+       up->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0);
        if (IS_ERR(up->gpios))
                return PTR_ERR(up->gpios);
 
index 90ca082935f635236a5c2ca5f4da48b99297b48f..3d245cd3d8e62082301b7061144ec2329cf16609 100644 (file)
@@ -265,7 +265,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
  *
  *     Audit @data of @size from @tty, if necessary.
  */
-void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+void tty_audit_add_data(struct tty_struct *tty, const void *data,
                        size_t size, unsigned icanon)
 {
        struct tty_audit_buf *buf;
index 0c41dbcb90b8bc7d8ab430d562206e7c2469411f..bcc8e1e8bb720996cf73438c67a397362173edca 100644 (file)
@@ -1282,18 +1282,22 @@ int tty_send_xchar(struct tty_struct *tty, char ch)
        int     was_stopped = tty->stopped;
 
        if (tty->ops->send_xchar) {
+               down_read(&tty->termios_rwsem);
                tty->ops->send_xchar(tty, ch);
+               up_read(&tty->termios_rwsem);
                return 0;
        }
 
        if (tty_write_lock(tty, 0) < 0)
                return -ERESTARTSYS;
 
+       down_read(&tty->termios_rwsem);
        if (was_stopped)
                start_tty(tty);
        tty->ops->write(tty, &ch, 1);
        if (was_stopped)
                stop_tty(tty);
+       up_read(&tty->termios_rwsem);
        tty_write_unlock(tty);
        return 0;
 }
index 9c5aebfe7053cbcae1fd65a95f3312509525e8e6..1445dd39aa6227ab641130ef7344eaba9f113b86 100644 (file)
@@ -1147,16 +1147,12 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                        spin_unlock_irq(&tty->flow_lock);
                        break;
                case TCIOFF:
-                       down_read(&tty->termios_rwsem);
                        if (STOP_CHAR(tty) != __DISABLED_CHAR)
                                retval = tty_send_xchar(tty, STOP_CHAR(tty));
-                       up_read(&tty->termios_rwsem);
                        break;
                case TCION:
-                       down_read(&tty->termios_rwsem);
                        if (START_CHAR(tty) != __DISABLED_CHAR)
                                retval = tty_send_xchar(tty, START_CHAR(tty));
-                       up_read(&tty->termios_rwsem);
                        break;
                default:
                        return -EINVAL;
index 5af8f1874c1aab02fc16dbb0950d7264caa282ca..629e3c865072035f14fd4e6ece5a2544bcbf713c 100644 (file)
@@ -592,7 +592,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        /* Restart the work queue in case no characters kick it off. Safe if
           already running */
-       schedule_work(&tty->port->buf.work);
+       tty_buffer_restart_work(tty->port);
 
        tty_unlock(tty);
        return retval;
index 6ccbf60cdd5c1204f77072a396d9791c6bfdcc2a..5a048b7b92e8f8c7821f3e0a6880f38ab3259733 100644 (file)
@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data {
        struct imx_usbmisc_data *usbmisc_data;
        bool supports_runtime_pm;
        bool in_lpm;
+       /* SoC before i.mx6 (except imx23/imx28) needs three clks */
+       bool need_three_clks;
+       struct clk *clk_ipg;
+       struct clk *clk_ahb;
+       struct clk *clk_per;
+       /* --------------------------------- */
 };
 
 /* Common functions shared by usbmisc drivers */
@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
 }
 
 /* End of common functions shared by usbmisc drivers*/
+static int imx_get_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret = 0;
+
+       data->clk_ipg = devm_clk_get(dev, "ipg");
+       if (IS_ERR(data->clk_ipg)) {
+               /* If the platform only needs one clocks */
+               data->clk = devm_clk_get(dev, NULL);
+               if (IS_ERR(data->clk)) {
+                       ret = PTR_ERR(data->clk);
+                       dev_err(dev,
+                               "Failed to get clks, err=%ld,%ld\n",
+                               PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
+                       return ret;
+               }
+               return ret;
+       }
+
+       data->clk_ahb = devm_clk_get(dev, "ahb");
+       if (IS_ERR(data->clk_ahb)) {
+               ret = PTR_ERR(data->clk_ahb);
+               dev_err(dev,
+                       "Failed to get ahb clock, err=%d\n", ret);
+               return ret;
+       }
+
+       data->clk_per = devm_clk_get(dev, "per");
+       if (IS_ERR(data->clk_per)) {
+               ret = PTR_ERR(data->clk_per);
+               dev_err(dev,
+                       "Failed to get per clock, err=%d\n", ret);
+               return ret;
+       }
+
+       data->need_three_clks = true;
+       return ret;
+}
+
+static int imx_prepare_enable_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (data->need_three_clks) {
+               ret = clk_prepare_enable(data->clk_ipg);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable ipg clk, err=%d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(data->clk_ahb);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable ahb clk, err=%d\n",
+                               ret);
+                       clk_disable_unprepare(data->clk_ipg);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(data->clk_per);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable per clk, err=%d\n",
+                               ret);
+                       clk_disable_unprepare(data->clk_ahb);
+                       clk_disable_unprepare(data->clk_ipg);
+                       return ret;
+               }
+       } else {
+               ret = clk_prepare_enable(data->clk);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable clk, err=%d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static void imx_disable_unprepare_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+
+       if (data->need_three_clks) {
+               clk_disable_unprepare(data->clk_per);
+               clk_disable_unprepare(data->clk_ahb);
+               clk_disable_unprepare(data->clk_ipg);
+       } else {
+               clk_disable_unprepare(data->clk);
+       }
+}
 
 static int ci_hdrc_imx_probe(struct platform_device *pdev)
 {
@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                .flags          = CI_HDRC_SET_NON_ZERO_TTHA,
        };
        int ret;
-       const struct of_device_id *of_id =
-                       of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
-       const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
+       const struct of_device_id *of_id;
+       const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
+
+       of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
+
+       imx_platform_flag = of_id->data;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
+       platform_set_drvdata(pdev, data);
        data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
        if (IS_ERR(data->usbmisc_data))
                return PTR_ERR(data->usbmisc_data);
 
-       data->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(data->clk)) {
-               dev_err(&pdev->dev,
-                       "Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
-               return PTR_ERR(data->clk);
-       }
+       ret = imx_get_clks(&pdev->dev);
+       if (ret)
+               return ret;
 
-       ret = clk_prepare_enable(data->clk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "Failed to prepare or enable clock, err=%d\n", ret);
+       ret = imx_prepare_enable_clks(&pdev->dev);
+       if (ret)
                return ret;
-       }
 
        data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
        if (IS_ERR(data->phy)) {
@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                goto disable_device;
        }
 
-       platform_set_drvdata(pdev, data);
-
        if (data->supports_runtime_pm) {
                pm_runtime_set_active(&pdev->dev);
                pm_runtime_enable(&pdev->dev);
@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 disable_device:
        ci_hdrc_remove_device(data->ci_pdev);
 err_clk:
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(&pdev->dev);
        return ret;
 }
 
@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
                pm_runtime_put_noidle(&pdev->dev);
        }
        ci_hdrc_remove_device(data->ci_pdev);
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(&pdev->dev);
 
        return 0;
 }
@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)
 
        dev_dbg(dev, "at %s\n", __func__);
 
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(dev);
        data->in_lpm = true;
 
        return 0;
@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
                return 0;
        }
 
-       ret = clk_prepare_enable(data->clk);
+       ret = imx_prepare_enable_clks(dev);
        if (ret)
                return ret;
 
@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
        return 0;
 
 clk_disable:
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(dev);
        return ret;
 }
 
index 080b7be3daf034939bd12c509353c041b6027f49..58c8485a0715ada6c585a29e23883f25091fa127 100644 (file)
@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
                return -EINVAL;
 
        pm_runtime_get_sync(ci->dev);
+       disable_irq(ci->irq);
        ci_role_stop(ci);
        ret = ci_role_start(ci, role);
+       enable_irq(ci->irq);
        pm_runtime_put_sync(ci->dev);
 
        return ret ? ret : count;
index 8223fe73ea85926477cf710227fc3907b5ad9ff1..391a1225b0ba330cd818028f240cb151e8ade65c 100644 (file)
@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
        return retval;
 }
 
+static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
+{
+       if (!ci_otg_is_fsm_mode(ci))
+               return;
+
+       mutex_lock(&ci->fsm.lock);
+       if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
+               ci->fsm.a_bidl_adis_tmout = 1;
+               ci_hdrc_otg_fsm_start(ci);
+       } else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
+               ci->fsm.protocol = PROTO_UNDEF;
+               ci->fsm.otg->state = OTG_STATE_UNDEFINED;
+       }
+       mutex_unlock(&ci->fsm.lock);
+}
+
 /**
  * ci_udc_stop: unregister a gadget driver
  */
@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
        ci->driver = NULL;
        spin_unlock_irqrestore(&ci->lock, flags);
 
+       ci_udc_stop_for_otg_fsm(ci);
        return 0;
 }
 
index fcea4eb36eeedbceac777ecd8d676e5ede74cba6..ab8b027e8cc870615d399abb631849875db72427 100644 (file)
@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct imx_usbmisc *data;
-       struct of_device_id *tmp_dev;
+       const struct of_device_id *of_id;
+
+       of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
 
-       tmp_dev = (struct of_device_id *)
-               of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
-       data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+       data->ops = (const struct usbmisc_ops *)of_id->data;
        platform_set_drvdata(pdev, data);
 
        return 0;
index 433bbc34a8a481ff15c8070e9917ecf1ec1455e8..071964c7847f1fbf148c2cb485fe0750e8518adc 100644 (file)
@@ -884,11 +884,11 @@ static int usblp_wwait(struct usblp *usblp, int nonblock)
 
        add_wait_queue(&usblp->wwait, &waita);
        for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
                if (mutex_lock_interruptible(&usblp->mut)) {
                        rc = -EINTR;
                        break;
                }
+               set_current_state(TASK_INTERRUPTIBLE);
                rc = usblp_wtest(usblp, nonblock);
                mutex_unlock(&usblp->mut);
                if (rc <= 0)
index a99c89e781264b2cc260409f9b27d3dbd32a85bf..dd280108758f3aff975f25653119d107b1e6cc3a 100644 (file)
@@ -77,8 +77,7 @@ config USB_OTG_BLACKLIST_HUB
 
 config USB_OTG_FSM
        tristate "USB 2.0 OTG FSM implementation"
-       depends on USB
-       select USB_OTG
+       depends on USB && USB_OTG
        select USB_PHY
        help
          Implements OTG Finite State Machine as specified in On-The-Go
index e79baf73c234f58bf3162bb9d52d5efce9bca1ca..571c21727ff9f5cb8c774eeb1178cfc55e8e88b4 100644 (file)
@@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
 {
-       if (hsotg->lx_state == DWC2_L2) {
+       if (hsotg->bus_suspended) {
                hsotg->flags.b.port_suspend_change = 1;
                usb_hcd_resume_root_hub(hsotg->priv);
-       } else {
-               hsotg->flags.b.port_l1_change = 1;
        }
+
+       if (hsotg->lx_state == DWC2_L1)
+               hsotg->flags.b.port_l1_change = 1;
 }
 
 /**
@@ -1428,8 +1429,8 @@ static void dwc2_wakeup_detected(unsigned long data)
        dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
                dwc2_readl(hsotg->regs + HPRT0));
 
-       hsotg->bus_suspended = 0;
        dwc2_hcd_rem_wakeup(hsotg);
+       hsotg->bus_suspended = 0;
 
        /* Change to L0 state */
        hsotg->lx_state = DWC2_L0;
index 5859b0fa19ee3f907b2bfa93945a6378ae10911a..e61d773cf65e71e27a41f3c7d8e5306939d08908 100644 (file)
@@ -108,7 +108,8 @@ static const struct dwc2_core_params params_rk3066 = {
        .host_ls_low_power_phy_clk      = -1,
        .ts_dline                       = -1,
        .reload_ctl                     = -1,
-       .ahbcfg                         = 0x7, /* INCR16 */
+       .ahbcfg                         = GAHBCFG_HBSTLEN_INCR16 <<
+                                         GAHBCFG_HBSTLEN_SHIFT,
        .uframe_sched                   = -1,
        .external_id_pin_ctl            = -1,
        .hibernation                    = -1,
index 77a622cb48ab1555a87dfaf279f5d25368672e99..009d83048c8c9ab51ae01191e3cb2aa30207d928 100644 (file)
@@ -34,6 +34,8 @@
 #define PCI_DEVICE_ID_INTEL_BSW                        0x22b7
 #define PCI_DEVICE_ID_INTEL_SPTLP              0x9d30
 #define PCI_DEVICE_ID_INTEL_SPTH               0xa130
+#define PCI_DEVICE_ID_INTEL_BXT                        0x0aaa
+#define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -210,6 +212,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
        {  }    /* Terminating Entry */
 };
index 55ba447fdf8bf56720eeac029ed4f96d932ee0ea..e24a01cc98df4a43f2fd556e44b1557dce778d33 100644 (file)
@@ -2744,11 +2744,33 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        }
 
        dwc->gadget.ops                 = &dwc3_gadget_ops;
-       dwc->gadget.max_speed           = USB_SPEED_SUPER;
        dwc->gadget.speed               = USB_SPEED_UNKNOWN;
        dwc->gadget.sg_supported        = true;
        dwc->gadget.name                = "dwc3-gadget";
 
+       /*
+        * FIXME We might be setting max_speed to <SUPER, however versions
+        * <2.20a of dwc3 have an issue with metastability (documented
+        * elsewhere in this driver) which tells us we can't set max speed to
+        * anything lower than SUPER.
+        *
+        * Because gadget.max_speed is only used by composite.c and function
+        * drivers (i.e. it won't go into dwc3's registers) we are allowing this
+        * to happen so we avoid sending SuperSpeed Capability descriptor
+        * together with our BOS descriptor as that could confuse host into
+        * thinking we can handle super speed.
+        *
+        * Note that, in fact, we won't even support GetBOS requests when speed
+        * is less than super speed because we don't have means, yet, to tell
+        * composite.c that we are USB 2.0 + LPM ECN.
+        */
+       if (dwc->revision < DWC3_REVISION_220A)
+               dwc3_trace(trace_dwc3_gadget,
+                               "Changing max_speed on rev %08x\n",
+                               dwc->revision);
+
+       dwc->gadget.max_speed           = dwc->maximum_speed;
+
        /*
         * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
         * on ep out.
index 294eb74fb078508f6889902e1a0c841f3b603ece..163d305e1200bb07a73357d7b5824d97b362b924 100644 (file)
@@ -64,6 +64,11 @@ struct gadget_info {
        char qw_sign[OS_STRING_QW_SIGN_LEN];
 };
 
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+        return container_of(to_config_group(item), struct gadget_info, group);
+}
+
 struct config_usb_cfg {
        struct config_group group;
        struct config_group strings_group;
@@ -74,6 +79,12 @@ struct config_usb_cfg {
        struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
 };
 
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct config_usb_cfg,
+                       group);
+}
+
 struct gadget_strings {
        struct usb_gadget_strings stringtab_dev;
        struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
@@ -117,32 +128,25 @@ static int usb_string_copy(const char *s, char **s_copy)
        return 0;
 }
 
-CONFIGFS_ATTR_STRUCT(gadget_info);
-CONFIGFS_ATTR_STRUCT(config_usb_cfg);
-
-#define GI_DEVICE_DESC_ITEM_ATTR(name) \
-       static struct gadget_info_attribute gadget_cdev_desc_##name = \
-               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
-                               gadget_dev_desc_##name##_show,          \
-                               gadget_dev_desc_##name##_store)
-
 #define GI_DEVICE_DESC_SIMPLE_R_u8(__name)     \
-       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
                        char *page)     \
 {      \
-       return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+       return sprintf(page, "0x%02x\n", \
+               to_gadget_info(item)->cdev.desc.__name); \
 }
 
 #define GI_DEVICE_DESC_SIMPLE_R_u16(__name)    \
-       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
                        char *page)     \
 {      \
-       return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+       return sprintf(page, "0x%04x\n", \
+               le16_to_cpup(&to_gadget_info(item)->cdev.desc.__name)); \
 }
 
 
 #define GI_DEVICE_DESC_SIMPLE_W_u8(_name)              \
-       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
                const char *page, size_t len)           \
 {                                                      \
        u8 val;                                         \
@@ -150,12 +154,12 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
        ret = kstrtou8(page, 0, &val);                  \
        if (ret)                                        \
                return ret;                             \
-       gi->cdev.desc._name = val;                      \
+       to_gadget_info(item)->cdev.desc._name = val;    \
        return len;                                     \
 }
 
 #define GI_DEVICE_DESC_SIMPLE_W_u16(_name)     \
-       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
                const char *page, size_t len)           \
 {                                                      \
        u16 val;                                        \
@@ -163,7 +167,7 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
        ret = kstrtou16(page, 0, &val);                 \
        if (ret)                                        \
                return ret;                             \
-       gi->cdev.desc._name = cpu_to_le16p(&val);       \
+       to_gadget_info(item)->cdev.desc._name = cpu_to_le16p(&val);     \
        return len;                                     \
 }
 
@@ -193,7 +197,7 @@ static ssize_t is_valid_bcd(u16 bcd_val)
        return 0;
 }
 
-static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdDevice_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 bcdDevice;
@@ -206,11 +210,11 @@ static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
        if (ret)
                return ret;
 
-       gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+       to_gadget_info(item)->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
        return len;
 }
 
-static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 bcdUSB;
@@ -223,13 +227,13 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
        if (ret)
                return ret;
 
-       gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+       to_gadget_info(item)->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
        return len;
 }
 
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%s\n", gi->udc_name ?: "");
+       return sprintf(page, "%s\n", to_gadget_info(item)->udc_name ?: "");
 }
 
 static int unregister_gadget(struct gadget_info *gi)
@@ -247,9 +251,10 @@ static int unregister_gadget(struct gadget_info *gi)
        return 0;
 }
 
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
                const char *page, size_t len)
 {
+       struct gadget_info *gi = to_gadget_info(item);
        char *name;
        int ret;
 
@@ -283,34 +288,29 @@ static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
        return ret;
 }
 
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
-GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
-GI_DEVICE_DESC_ITEM_ATTR(idVendor);
-GI_DEVICE_DESC_ITEM_ATTR(idProduct);
-GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
-GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
+CONFIGFS_ATTR(gadget_dev_desc_, bMaxPacketSize0);
+CONFIGFS_ATTR(gadget_dev_desc_, idVendor);
+CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
+CONFIGFS_ATTR(gadget_dev_desc_, UDC);
 
 static struct configfs_attribute *gadget_root_attrs[] = {
-       &gadget_cdev_desc_bDeviceClass.attr,
-       &gadget_cdev_desc_bDeviceSubClass.attr,
-       &gadget_cdev_desc_bDeviceProtocol.attr,
-       &gadget_cdev_desc_bMaxPacketSize0.attr,
-       &gadget_cdev_desc_idVendor.attr,
-       &gadget_cdev_desc_idProduct.attr,
-       &gadget_cdev_desc_bcdDevice.attr,
-       &gadget_cdev_desc_bcdUSB.attr,
-       &gadget_cdev_desc_UDC.attr,
+       &gadget_dev_desc_attr_bDeviceClass,
+       &gadget_dev_desc_attr_bDeviceSubClass,
+       &gadget_dev_desc_attr_bDeviceProtocol,
+       &gadget_dev_desc_attr_bMaxPacketSize0,
+       &gadget_dev_desc_attr_idVendor,
+       &gadget_dev_desc_attr_idProduct,
+       &gadget_dev_desc_attr_bcdDevice,
+       &gadget_dev_desc_attr_bcdUSB,
+       &gadget_dev_desc_attr_UDC,
        NULL,
 };
 
-static inline struct gadget_info *to_gadget_info(struct config_item *item)
-{
-        return container_of(to_config_group(item), struct gadget_info, group);
-}
-
 static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
 {
         return container_of(to_config_group(item), struct gadget_strings,
@@ -324,12 +324,6 @@ static inline struct gadget_config_name *to_gadget_config_name(
                         group);
 }
 
-static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
-{
-       return container_of(to_config_group(item), struct config_usb_cfg,
-                       group);
-}
-
 static inline struct usb_function_instance *to_usb_function_instance(
                struct config_item *item)
 {
@@ -348,12 +342,8 @@ static void gadget_info_attr_release(struct config_item *item)
        kfree(gi);
 }
 
-CONFIGFS_ATTR_OPS(gadget_info);
-
 static struct configfs_item_operations gadget_root_item_ops = {
        .release                = gadget_info_attr_release,
-       .show_attribute         = gadget_info_attr_show,
-       .store_attribute        = gadget_info_attr_store,
 };
 
 static void gadget_config_attr_release(struct config_item *item)
@@ -454,24 +444,20 @@ static int config_usb_cfg_unlink(
        return 0;
 }
 
-CONFIGFS_ATTR_OPS(config_usb_cfg);
-
 static struct configfs_item_operations gadget_config_item_ops = {
        .release                = gadget_config_attr_release,
-       .show_attribute         = config_usb_cfg_attr_show,
-       .store_attribute        = config_usb_cfg_attr_store,
        .allow_link             = config_usb_cfg_link,
        .drop_link              = config_usb_cfg_unlink,
 };
 
 
-static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_show(struct config_item *item,
                char *page)
 {
-       return sprintf(page, "%u\n", cfg->c.MaxPower);
+       return sprintf(page, "%u\n", to_config_usb_cfg(item)->c.MaxPower);
 }
 
-static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_store(struct config_item *item,
                const char *page, size_t len)
 {
        u16 val;
@@ -481,17 +467,18 @@ static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
                return ret;
        if (DIV_ROUND_UP(val, 8) > 0xff)
                return -ERANGE;
-       cfg->c.MaxPower = val;
+       to_config_usb_cfg(item)->c.MaxPower = val;
        return len;
 }
 
-static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_item *item,
                char *page)
 {
-       return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+       return sprintf(page, "0x%02x\n",
+               to_config_usb_cfg(item)->c.bmAttributes);
 }
 
-static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_item *item,
                const char *page, size_t len)
 {
        u8 val;
@@ -504,22 +491,16 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
        if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
                                USB_CONFIG_ATT_WAKEUP))
                return -EINVAL;
-       cfg->c.bmAttributes = val;
+       to_config_usb_cfg(item)->c.bmAttributes = val;
        return len;
 }
 
-#define CFG_CONFIG_DESC_ITEM_ATTR(name)        \
-       static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
-               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
-                               gadget_config_desc_##name##_show,       \
-                               gadget_config_desc_##name##_store)
-
-CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
-CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+CONFIGFS_ATTR(gadget_config_desc_, MaxPower);
+CONFIGFS_ATTR(gadget_config_desc_, bmAttributes);
 
 static struct configfs_attribute *gadget_config_attrs[] = {
-       &gadget_usb_cfg_MaxPower.attr,
-       &gadget_usb_cfg_bmAttributes.attr,
+       &gadget_config_desc_attr_MaxPower,
+       &gadget_config_desc_attr_bmAttributes,
        NULL,
 };
 
@@ -616,11 +597,10 @@ static struct config_item_type functions_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(gadget_config_name);
 GS_STRINGS_RW(gadget_config_name, configuration);
 
 static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
-       &gadget_config_name_configuration.attr,
+       &gadget_config_name_attr_configuration,
        NULL,
 };
 
@@ -719,15 +699,14 @@ static struct config_item_type config_desc_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(gadget_strings);
 GS_STRINGS_RW(gadget_strings, manufacturer);
 GS_STRINGS_RW(gadget_strings, product);
 GS_STRINGS_RW(gadget_strings, serialnumber);
 
 static struct configfs_attribute *gadget_strings_langid_attrs[] = {
-       &gadget_strings_manufacturer.attr,
-       &gadget_strings_product.attr,
-       &gadget_strings_serialnumber.attr,
+       &gadget_strings_attr_manufacturer,
+       &gadget_strings_attr_product,
+       &gadget_strings_attr_serialnumber,
        NULL,
 };
 
@@ -751,27 +730,25 @@ static inline struct os_desc *to_os_desc(struct config_item *item)
        return container_of(to_config_group(item), struct os_desc, group);
 }
 
-CONFIGFS_ATTR_STRUCT(os_desc);
-CONFIGFS_ATTR_OPS(os_desc);
-
-static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
+static inline struct gadget_info *os_desc_item_to_gadget_info(
+               struct config_item *item)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+       return to_gadget_info(to_os_desc(item)->group.cg_item.ci_parent);
+}
 
-       return sprintf(page, "%d", gi->use_os_desc);
+static ssize_t os_desc_use_show(struct config_item *item, char *page)
+{
+       return sprintf(page, "%d",
+                       os_desc_item_to_gadget_info(item)->use_os_desc);
 }
 
-static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_use_store(struct config_item *item, const char *page,
                                 size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int ret;
        bool use;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
        mutex_lock(&gi->lock);
        ret = strtobool(page, &use);
        if (!ret) {
@@ -783,29 +760,19 @@ static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
        return ret;
 }
 
-static struct os_desc_attribute os_desc_use =
-       __CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
-                       os_desc_use_show,
-                       os_desc_use_store);
-
-static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
-       return sprintf(page, "%d", gi->b_vendor_code);
+       return sprintf(page, "%d",
+                       os_desc_item_to_gadget_info(item)->b_vendor_code);
 }
 
-static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
+static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
                                           const char *page, size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int ret;
        u8 b_vendor_code;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
        mutex_lock(&gi->lock);
        ret = kstrtou8(page, 0, &b_vendor_code);
        if (!ret) {
@@ -817,29 +784,20 @@ static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
        return ret;
 }
 
-static struct os_desc_attribute os_desc_b_vendor_code =
-       __CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
-                       os_desc_b_vendor_code_show,
-                       os_desc_b_vendor_code_store);
-
-static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
 {
-       struct gadget_info *gi;
-
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
 
        memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
-
        return OS_STRING_QW_SIGN_LEN;
 }
 
-static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
                                     size_t len)
 {
-       struct gadget_info *gi;
+       struct gadget_info *gi = os_desc_item_to_gadget_info(item);
        int res, l;
 
-       gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
        l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
        if (page[l - 1] == '\n')
                --l;
@@ -855,15 +813,14 @@ static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
        return res;
 }
 
-static struct os_desc_attribute os_desc_qw_sign =
-       __CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
-                       os_desc_qw_sign_show,
-                       os_desc_qw_sign_store);
+CONFIGFS_ATTR(os_desc_, use);
+CONFIGFS_ATTR(os_desc_, b_vendor_code);
+CONFIGFS_ATTR(os_desc_, qw_sign);
 
 static struct configfs_attribute *os_desc_attrs[] = {
-       &os_desc_use.attr,
-       &os_desc_b_vendor_code.attr,
-       &os_desc_qw_sign.attr,
+       &os_desc_attr_use,
+       &os_desc_attr_b_vendor_code,
+       &os_desc_attr_qw_sign,
        NULL,
 };
 
@@ -926,8 +883,6 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
 
 static struct configfs_item_operations os_desc_ops = {
        .release                = os_desc_attr_release,
-       .show_attribute         = os_desc_attr_show,
-       .store_attribute        = os_desc_attr_store,
        .allow_link             = os_desc_link,
        .drop_link              = os_desc_unlink,
 };
@@ -938,28 +893,21 @@ static struct config_item_type os_desc_type = {
        .ct_owner       = THIS_MODULE,
 };
 
-CONFIGFS_ATTR_STRUCT(usb_os_desc);
-CONFIGFS_ATTR_OPS(usb_os_desc);
-
-
 static inline struct usb_os_desc_ext_prop
 *to_usb_os_desc_ext_prop(struct config_item *item)
 {
        return container_of(item, struct usb_os_desc_ext_prop, item);
 }
 
-CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
-CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
-
-static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
-                                 char *page)
+static ssize_t ext_prop_type_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d", ext_prop->type);
+       return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
 }
 
-static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_type_store(struct config_item *item,
                                   const char *page, size_t len)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
        u8 type;
        int ret;
@@ -997,9 +945,9 @@ static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
        return ret;
 }
 
-static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
-                                 char *page)
+static ssize_t ext_prop_data_show(struct config_item *item, char *page)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        int len = ext_prop->data_len;
 
        if (ext_prop->type == USB_EXT_PROP_UNICODE ||
@@ -1011,9 +959,10 @@ static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
        return len;
 }
 
-static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_data_store(struct config_item *item,
                                   const char *page, size_t len)
 {
+       struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
        struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
        char *new_data;
        size_t ret_len = len;
@@ -1044,17 +993,12 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
        return ret_len;
 }
 
-static struct usb_os_desc_ext_prop_attribute ext_prop_type =
-       __CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
-                       ext_prop_type_show, ext_prop_type_store);
-
-static struct usb_os_desc_ext_prop_attribute ext_prop_data =
-       __CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
-                       ext_prop_data_show, ext_prop_data_store);
+CONFIGFS_ATTR(ext_prop_, type);
+CONFIGFS_ATTR(ext_prop_, data);
 
 static struct configfs_attribute *ext_prop_attrs[] = {
-       &ext_prop_type.attr,
-       &ext_prop_data.attr,
+       &ext_prop_attr_type,
+       &ext_prop_attr_data,
        NULL,
 };
 
@@ -1067,8 +1011,6 @@ static void usb_os_desc_ext_prop_release(struct config_item *item)
 
 static struct configfs_item_operations ext_prop_ops = {
        .release                = usb_os_desc_ext_prop_release,
-       .show_attribute         = usb_os_desc_ext_prop_attr_show,
-       .store_attribute        = usb_os_desc_ext_prop_attr_store,
 };
 
 static struct config_item *ext_prop_make(
@@ -1137,21 +1079,17 @@ static struct configfs_group_operations interf_grp_ops = {
        .drop_item      = &ext_prop_drop,
 };
 
-static struct configfs_item_operations interf_item_ops = {
-       .show_attribute         = usb_os_desc_attr_show,
-       .store_attribute        = usb_os_desc_attr_store,
-};
-
-static ssize_t interf_grp_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_show(struct config_item *item,
                                             char *page)
 {
-       memcpy(page, desc->ext_compat_id, 8);
+       memcpy(page, to_usb_os_desc(item)->ext_compat_id, 8);
        return 8;
 }
 
-static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_store(struct config_item *item,
                                              const char *page, size_t len)
 {
+       struct usb_os_desc *desc = to_usb_os_desc(item);
        int l;
 
        l = min_t(int, 8, len);
@@ -1167,21 +1105,17 @@ static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
        return len;
 }
 
-static struct usb_os_desc_attribute interf_grp_attr_compatible_id =
-       __CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
-                       interf_grp_compatible_id_show,
-                       interf_grp_compatible_id_store);
-
-static ssize_t interf_grp_sub_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_show(struct config_item *item,
                                                 char *page)
 {
-       memcpy(page, desc->ext_compat_id + 8, 8);
+       memcpy(page, to_usb_os_desc(item)->ext_compat_id + 8, 8);
        return 8;
 }
 
-static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_store(struct config_item *item,
                                                  const char *page, size_t len)
 {
+       struct usb_os_desc *desc = to_usb_os_desc(item);
        int l;
 
        l = min_t(int, 8, len);
@@ -1197,14 +1131,12 @@ static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
        return len;
 }
 
-static struct usb_os_desc_attribute interf_grp_attr_sub_compatible_id =
-       __CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
-                       interf_grp_sub_compatible_id_show,
-                       interf_grp_sub_compatible_id_store);
+CONFIGFS_ATTR(interf_grp_, compatible_id);
+CONFIGFS_ATTR(interf_grp_, sub_compatible_id);
 
 static struct configfs_attribute *interf_grp_attrs[] = {
-       &interf_grp_attr_compatible_id.attr,
-       &interf_grp_attr_sub_compatible_id.attr,
+       &interf_grp_attr_compatible_id,
+       &interf_grp_attr_sub_compatible_id,
        NULL
 };
 
@@ -1242,7 +1174,6 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
        f_default_groups[0] = os_desc_group;
 
        os_desc_group->default_groups = interface_groups;
-       interface_type->ct_item_ops = &interf_item_ops;
        interface_type->ct_group_ops = &interf_grp_ops;
        interface_type->ct_attrs = interf_grp_attrs;
        interface_type->ct_owner = owner;
index 22e723d12d36ff4a6a24b07b703ac6172cf799ba..2fa1e80a3ce7bbdd941ddf30fb79e8860812a907 100644 (file)
@@ -761,21 +761,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
                        func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_acm_attr_show(struct config_item *item,
-                                struct configfs_attribute *attr,
-                                char *page)
-{
-       struct f_serial_opts *opts = to_f_serial_opts(item);
-       struct f_serial_opts_attribute *f_serial_opts_attr =
-               container_of(attr, struct f_serial_opts_attribute, attr);
-       ssize_t ret = 0;
-
-       if (f_serial_opts_attr->show)
-               ret = f_serial_opts_attr->show(opts, page);
-       return ret;
-}
-
 static void acm_attr_release(struct config_item *item)
 {
        struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -785,20 +770,17 @@ static void acm_attr_release(struct config_item *item)
 
 static struct configfs_item_operations acm_item_ops = {
        .release                = acm_attr_release,
-       .show_attribute         = f_acm_attr_show,
 };
 
-static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_acm_port_num_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", opts->port_num);
+       return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
 }
 
-static struct f_serial_opts_attribute f_acm_port_num =
-       __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
-
+CONFIGFS_ATTR_RO(f_acm_port_, num);
 
 static struct configfs_attribute *acm_attrs[] = {
-       &f_acm_port_num.attr,
+       &f_acm_port_attr_num,
        NULL,
 };
 
index 4abca70cdaab9d52e529dcc85b2dabb30137d7e1..7ad60ee419144fd89b6d109439dcacd99c6a3db7 100644 (file)
@@ -838,10 +838,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
 
 static struct configfs_attribute *ecm_attrs[] = {
-       &f_ecm_opts_dev_addr.attr,
-       &f_ecm_opts_host_addr.attr,
-       &f_ecm_opts_qmult.attr,
-       &f_ecm_opts_ifname.attr,
+       &ecm_opts_attr_dev_addr,
+       &ecm_opts_attr_host_addr,
+       &ecm_opts_attr_qmult,
+       &ecm_opts_attr_ifname,
        NULL,
 };
 
index 9a55757c729b2f59f1d512a8f4f67dffa89c5feb..cad35a502d3f73a64759cd8eb8d541d36104cbac 100644 (file)
@@ -545,10 +545,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem);
 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem);
 
 static struct configfs_attribute *eem_attrs[] = {
-       &f_eem_opts_dev_addr.attr,
-       &f_eem_opts_host_addr.attr,
-       &f_eem_opts_qmult.attr,
-       &f_eem_opts_ifname.attr,
+       &eem_opts_attr_dev_addr,
+       &eem_opts_attr_host_addr,
+       &eem_opts_attr_qmult,
+       &eem_opts_attr_ifname,
        NULL,
 };
 
index 21fcf18f53a0409ed00bc302ac62b4f012e5c766..99285b416308f84917a6500aad64daff34c2ce05 100644 (file)
@@ -705,9 +705,6 @@ static inline struct f_hid_opts *to_f_hid_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_hid_opts);
-CONFIGFS_ATTR_OPS(f_hid_opts);
-
 static void hid_attr_release(struct config_item *item)
 {
        struct f_hid_opts *opts = to_f_hid_opts(item);
@@ -717,13 +714,12 @@ static void hid_attr_release(struct config_item *item)
 
 static struct configfs_item_operations hidg_item_ops = {
        .release        = hid_attr_release,
-       .show_attribute = f_hid_opts_attr_show,
-       .store_attribute = f_hid_opts_attr_store,
 };
 
 #define F_HID_OPT(name, prec, limit)                                   \
-static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
+static ssize_t f_hid_opts_##name##_show(struct config_item *item, char *page)\
 {                                                                      \
+       struct f_hid_opts *opts = to_f_hid_opts(item);                  \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -733,9 +729,10 @@ static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t f_hid_opts_##name##_store(struct f_hid_opts *opts,      \
+static ssize_t f_hid_opts_##name##_store(struct config_item *item,     \
                                         const char *page, size_t len)  \
 {                                                                      \
+       struct f_hid_opts *opts = to_f_hid_opts(item);                  \
        int ret;                                                        \
        u##prec num;                                                    \
                                                                        \
@@ -761,16 +758,15 @@ end:                                                                      \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_hid_opts_attribute f_hid_opts_##name =                 \
-       __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_hid_opts_##name##_show,\
-                       f_hid_opts_##name##_store)
+CONFIGFS_ATTR(f_hid_opts_, name)
 
 F_HID_OPT(subclass, 8, 255);
 F_HID_OPT(protocol, 8, 255);
 F_HID_OPT(report_length, 16, 65535);
 
-static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
+static ssize_t f_hid_opts_report_desc_show(struct config_item *item, char *page)
 {
+       struct f_hid_opts *opts = to_f_hid_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -781,9 +777,10 @@ static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_hid_opts_report_desc_store(struct f_hid_opts *opts,
+static ssize_t f_hid_opts_report_desc_store(struct config_item *item,
                                            const char *page, size_t len)
 {
+       struct f_hid_opts *opts = to_f_hid_opts(item);
        int ret = -EBUSY;
        char *d;
 
@@ -810,16 +807,13 @@ static ssize_t f_hid_opts_report_desc_store(struct f_hid_opts *opts,
        return ret;
 }
 
-static struct f_hid_opts_attribute f_hid_opts_report_desc =
-       __CONFIGFS_ATTR(report_desc, S_IRUGO | S_IWUSR,
-                       f_hid_opts_report_desc_show,
-                       f_hid_opts_report_desc_store);
+CONFIGFS_ATTR(f_hid_opts_, report_desc);
 
 static struct configfs_attribute *hid_attrs[] = {
-       &f_hid_opts_subclass.attr,
-       &f_hid_opts_protocol.attr,
-       &f_hid_opts_report_length.attr,
-       &f_hid_opts_report_desc.attr,
+       &f_hid_opts_attr_subclass,
+       &f_hid_opts_attr_protocol,
+       &f_hid_opts_attr_report_length,
+       &f_hid_opts_attr_report_desc,
        NULL,
 };
 
index 6b2102bc069973554db95d3311470b0545067727..ddc3aad886b7457dd0ab4c79587104b474889ca0 100644 (file)
@@ -329,7 +329,7 @@ static int alloc_requests(struct usb_composite_dev *cdev,
        for (i = 0; i < loop->qlen && result == 0; i++) {
                result = -ENOMEM;
 
-               in_req = usb_ep_alloc_request(loop->in_ep, GFP_KERNEL);
+               in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
                if (!in_req)
                        goto fail;
 
@@ -465,9 +465,6 @@ static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_lb_opts);
-CONFIGFS_ATTR_OPS(f_lb_opts);
-
 static void lb_attr_release(struct config_item *item)
 {
        struct f_lb_opts *lb_opts = to_f_lb_opts(item);
@@ -477,12 +474,11 @@ static void lb_attr_release(struct config_item *item)
 
 static struct configfs_item_operations lb_item_ops = {
        .release                = lb_attr_release,
-       .show_attribute         = f_lb_opts_attr_show,
-       .store_attribute        = f_lb_opts_attr_store,
 };
 
-static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_qlen_show(struct config_item *item, char *page)
 {
+       struct f_lb_opts *opts = to_f_lb_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -492,9 +488,10 @@ static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_qlen_store(struct config_item *item,
                                    const char *page, size_t len)
 {
+       struct f_lb_opts *opts = to_f_lb_opts(item);
        int ret;
        u32 num;
 
@@ -515,13 +512,11 @@ static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
        return ret;
 }
 
-static struct f_lb_opts_attribute f_lb_opts_qlen =
-       __CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
-                       f_lb_opts_qlen_show,
-                       f_lb_opts_qlen_store);
+CONFIGFS_ATTR(f_lb_opts_, qlen);
 
-static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_bulk_buflen_show(struct config_item *item, char *page)
 {
+       struct f_lb_opts *opts = to_f_lb_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -531,9 +526,10 @@ static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_bulk_buflen_store(struct config_item *item,
                                    const char *page, size_t len)
 {
+       struct f_lb_opts *opts = to_f_lb_opts(item);
        int ret;
        u32 num;
 
@@ -554,14 +550,11 @@ static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
        return ret;
 }
 
-static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
-       __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
-                       f_lb_opts_bulk_buflen_show,
-                       f_lb_opts_bulk_buflen_store);
+CONFIGFS_ATTR(f_lb_opts_, bulk_buflen);
 
 static struct configfs_attribute *lb_attrs[] = {
-       &f_lb_opts_qlen.attr,
-       &f_lb_opts_bulk_buflen.attr,
+       &f_lb_opts_attr_qlen,
+       &f_lb_opts_attr_bulk_buflen,
        NULL,
 };
 
index 5ec533826621c7cfcb0975f9084f0ec4df3b7cf1..223ccf89d2263fb6483a1a22116a3743c9d7ed8e 100644 (file)
@@ -3140,9 +3140,6 @@ static inline struct fsg_opts *to_fsg_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(fsg_lun_opts);
-CONFIGFS_ATTR_OPS(fsg_lun_opts);
-
 static void fsg_lun_attr_release(struct config_item *item)
 {
        struct fsg_lun_opts *lun_opts;
@@ -3153,110 +3150,93 @@ static void fsg_lun_attr_release(struct config_item *item)
 
 static struct configfs_item_operations fsg_lun_item_ops = {
        .release                = fsg_lun_attr_release,
-       .show_attribute         = fsg_lun_opts_attr_show,
-       .store_attribute        = fsg_lun_opts_attr_store,
 };
 
-static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_file_show(struct config_item *item, char *page)
 {
-       struct fsg_opts *fsg_opts;
-
-       fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+       struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+       struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
 
        return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page);
 }
 
-static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_file_store(struct config_item *item,
                                       const char *page, size_t len)
 {
-       struct fsg_opts *fsg_opts;
-
-       fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+       struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+       struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
 
        return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len);
 }
 
-static struct fsg_lun_opts_attribute fsg_lun_opts_file =
-       __CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show,
-                       fsg_lun_opts_file_store);
+CONFIGFS_ATTR(fsg_lun_opts_, file);
 
-static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_ro_show(struct config_item *item, char *page)
 {
-       return fsg_show_ro(opts->lun, page);
+       return fsg_show_ro(to_fsg_lun_opts(item)->lun, page);
 }
 
-static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_ro_store(struct config_item *item,
                                       const char *page, size_t len)
 {
-       struct fsg_opts *fsg_opts;
-
-       fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+       struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+       struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
 
        return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len);
 }
 
-static struct fsg_lun_opts_attribute fsg_lun_opts_ro =
-       __CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show,
-                       fsg_lun_opts_ro_store);
+CONFIGFS_ATTR(fsg_lun_opts_, ro);
 
-static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_show(struct config_item *item,
                                           char *page)
 {
-       return fsg_show_removable(opts->lun, page);
+       return fsg_show_removable(to_fsg_lun_opts(item)->lun, page);
 }
 
-static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_store(struct config_item *item,
                                       const char *page, size_t len)
 {
-       return fsg_store_removable(opts->lun, page, len);
+       return fsg_store_removable(to_fsg_lun_opts(item)->lun, page, len);
 }
 
-static struct fsg_lun_opts_attribute fsg_lun_opts_removable =
-       __CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR,
-                       fsg_lun_opts_removable_show,
-                       fsg_lun_opts_removable_store);
+CONFIGFS_ATTR(fsg_lun_opts_, removable);
 
-static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_cdrom_show(struct config_item *item, char *page)
 {
-       return fsg_show_cdrom(opts->lun, page);
+       return fsg_show_cdrom(to_fsg_lun_opts(item)->lun, page);
 }
 
-static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_cdrom_store(struct config_item *item,
                                       const char *page, size_t len)
 {
-       struct fsg_opts *fsg_opts;
-
-       fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+       struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+       struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
 
        return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page,
                               len);
 }
 
-static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom =
-       __CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show,
-                       fsg_lun_opts_cdrom_store);
+CONFIGFS_ATTR(fsg_lun_opts_, cdrom);
 
-static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_nofua_show(struct config_item *item, char *page)
 {
-       return fsg_show_nofua(opts->lun, page);
+       return fsg_show_nofua(to_fsg_lun_opts(item)->lun, page);
 }
 
-static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
                                       const char *page, size_t len)
 {
-       return fsg_store_nofua(opts->lun, page, len);
+       return fsg_store_nofua(to_fsg_lun_opts(item)->lun, page, len);
 }
 
-static struct fsg_lun_opts_attribute fsg_lun_opts_nofua =
-       __CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show,
-                       fsg_lun_opts_nofua_store);
+CONFIGFS_ATTR(fsg_lun_opts_, nofua);
 
 static struct configfs_attribute *fsg_lun_attrs[] = {
-       &fsg_lun_opts_file.attr,
-       &fsg_lun_opts_ro.attr,
-       &fsg_lun_opts_removable.attr,
-       &fsg_lun_opts_cdrom.attr,
-       &fsg_lun_opts_nofua.attr,
+       &fsg_lun_opts_attr_file,
+       &fsg_lun_opts_attr_ro,
+       &fsg_lun_opts_attr_removable,
+       &fsg_lun_opts_attr_cdrom,
+       &fsg_lun_opts_attr_nofua,
        NULL,
 };
 
@@ -3348,9 +3328,6 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
        config_item_put(item);
 }
 
-CONFIGFS_ATTR_STRUCT(fsg_opts);
-CONFIGFS_ATTR_OPS(fsg_opts);
-
 static void fsg_attr_release(struct config_item *item)
 {
        struct fsg_opts *opts = to_fsg_opts(item);
@@ -3360,12 +3337,11 @@ static void fsg_attr_release(struct config_item *item)
 
 static struct configfs_item_operations fsg_item_ops = {
        .release                = fsg_attr_release,
-       .show_attribute         = fsg_opts_attr_show,
-       .store_attribute        = fsg_opts_attr_store,
 };
 
-static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_stall_show(struct config_item *item, char *page)
 {
+       struct fsg_opts *opts = to_fsg_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -3375,9 +3351,10 @@ static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
        return result;
 }
 
-static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
+static ssize_t fsg_opts_stall_store(struct config_item *item, const char *page,
                                    size_t len)
 {
+       struct fsg_opts *opts = to_fsg_opts(item);
        int ret;
        bool stall;
 
@@ -3399,13 +3376,12 @@ static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
        return ret;
 }
 
-static struct fsg_opts_attribute fsg_opts_stall =
-       __CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show,
-                       fsg_opts_stall_store);
+CONFIGFS_ATTR(fsg_opts_, stall);
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
-static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_num_buffers_show(struct config_item *item, char *page)
 {
+       struct fsg_opts *opts = to_fsg_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -3415,9 +3391,10 @@ static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
        return result;
 }
 
-static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts,
+static ssize_t fsg_opts_num_buffers_store(struct config_item *item,
                                          const char *page, size_t len)
 {
+       struct fsg_opts *opts = to_fsg_opts(item);
        int ret;
        u8 num;
 
@@ -3442,17 +3419,13 @@ static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts,
        return ret;
 }
 
-static struct fsg_opts_attribute fsg_opts_num_buffers =
-       __CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR,
-                       fsg_opts_num_buffers_show,
-                       fsg_opts_num_buffers_store);
-
+CONFIGFS_ATTR(fsg_opts_, num_buffers);
 #endif
 
 static struct configfs_attribute *fsg_attrs[] = {
-       &fsg_opts_stall.attr,
+       &fsg_opts_attr_stall,
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
-       &fsg_opts_num_buffers.attr,
+       &fsg_opts_attr_num_buffers,
 #endif
        NULL,
 };
index ce3c8a629266c12d6de7638f2c9900af4085cd83..42acb45e1ab42dd9436244bec16d4903603d6089 100644 (file)
@@ -902,9 +902,6 @@ static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_midi_opts);
-CONFIGFS_ATTR_OPS(f_midi_opts);
-
 static void midi_attr_release(struct config_item *item)
 {
        struct f_midi_opts *opts = to_f_midi_opts(item);
@@ -914,13 +911,12 @@ static void midi_attr_release(struct config_item *item)
 
 static struct configfs_item_operations midi_item_ops = {
        .release        = midi_attr_release,
-       .show_attribute = f_midi_opts_attr_show,
-       .store_attribute = f_midi_opts_attr_store,
 };
 
 #define F_MIDI_OPT(name, test_limit, limit)                            \
-static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
+static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \
 {                                                                      \
+       struct f_midi_opts *opts = to_f_midi_opts(item);                \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -930,9 +926,10 @@ static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t f_midi_opts_##name##_store(struct f_midi_opts *opts,    \
+static ssize_t f_midi_opts_##name##_store(struct config_item *item,    \
                                         const char *page, size_t len)  \
 {                                                                      \
+       struct f_midi_opts *opts = to_f_midi_opts(item);                \
        int ret;                                                        \
        u32 num;                                                        \
                                                                        \
@@ -958,9 +955,7 @@ end:                                                                        \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_midi_opts_attribute f_midi_opts_##name =               \
-       __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_midi_opts_##name##_show, \
-                       f_midi_opts_##name##_store)
+CONFIGFS_ATTR(f_midi_opts_, name);
 
 F_MIDI_OPT(index, true, SNDRV_CARDS);
 F_MIDI_OPT(buflen, false, 0);
@@ -968,8 +963,9 @@ F_MIDI_OPT(qlen, false, 0);
 F_MIDI_OPT(in_ports, true, MAX_PORTS);
 F_MIDI_OPT(out_ports, true, MAX_PORTS);
 
-static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
+static ssize_t f_midi_opts_id_show(struct config_item *item, char *page)
 {
+       struct f_midi_opts *opts = to_f_midi_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -985,9 +981,10 @@ static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts,
+static ssize_t f_midi_opts_id_store(struct config_item *item,
                                    const char *page, size_t len)
 {
+       struct f_midi_opts *opts = to_f_midi_opts(item);
        int ret;
        char *c;
 
@@ -1012,17 +1009,15 @@ static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts,
        return ret;
 }
 
-static struct f_midi_opts_attribute f_midi_opts_id =
-       __CONFIGFS_ATTR(id, S_IRUGO | S_IWUSR, f_midi_opts_id_show,
-                       f_midi_opts_id_store);
+CONFIGFS_ATTR(f_midi_opts_, id);
 
 static struct configfs_attribute *midi_attrs[] = {
-       &f_midi_opts_index.attr,
-       &f_midi_opts_buflen.attr,
-       &f_midi_opts_qlen.attr,
-       &f_midi_opts_in_ports.attr,
-       &f_midi_opts_out_ports.attr,
-       &f_midi_opts_id.attr,
+       &f_midi_opts_attr_index,
+       &f_midi_opts_attr_buflen,
+       &f_midi_opts_attr_qlen,
+       &f_midi_opts_attr_in_ports,
+       &f_midi_opts_attr_out_ports,
+       &f_midi_opts_attr_id,
        NULL,
 };
 
index b6f7ed7d48a7fa6a297ccfeca6440465593462be..7ad798ace1e5b5d60c15712510fcf6b09ac81c86 100644 (file)
@@ -1488,10 +1488,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm);
 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm);
 
 static struct configfs_attribute *ncm_attrs[] = {
-       &f_ncm_opts_dev_addr.attr,
-       &f_ncm_opts_host_addr.attr,
-       &f_ncm_opts_qmult.attr,
-       &f_ncm_opts_ifname.attr,
+       &ncm_opts_attr_dev_addr,
+       &ncm_opts_attr_host_addr,
+       &ncm_opts_attr_qmult,
+       &ncm_opts_attr_ifname,
        NULL,
 };
 
index 1c3d30ad2f92cb3edba2ab0eb3ca490378de86f1..d6396e0909eeb45898541094cb2347b4d38bde24 100644 (file)
@@ -387,22 +387,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_obex_attr_show(struct config_item *item,
-                               struct configfs_attribute *attr,
-                               char *page)
-{
-       struct f_serial_opts *opts = to_f_serial_opts(item);
-       struct f_serial_opts_attribute *f_serial_opts_attr =
-               container_of(attr, struct f_serial_opts_attribute, attr);
-       ssize_t ret = 0;
-
-       if (f_serial_opts_attr->show)
-               ret = f_serial_opts_attr->show(opts, page);
-
-       return ret;
-}
-
 static void obex_attr_release(struct config_item *item)
 {
        struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -412,19 +396,17 @@ static void obex_attr_release(struct config_item *item)
 
 static struct configfs_item_operations obex_item_ops = {
        .release        = obex_attr_release,
-       .show_attribute = f_obex_attr_show,
 };
 
-static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_obex_port_num_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", opts->port_num);
+       return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
 }
 
-static struct f_serial_opts_attribute f_obex_port_num =
-       __CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+CONFIGFS_ATTR_RO(f_obex_, port_num);
 
 static struct configfs_attribute *acm_attrs[] = {
-       &f_obex_port_num.attr,
+       &f_obex_attr_port_num,
        NULL,
 };
 
index 62a198754029e1f707147a12713f758a186cdd8e..157441dbfeba861d4d877f8009dca6fb44acd740 100644 (file)
@@ -583,21 +583,6 @@ static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item)
                        func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_phonet_opts);
-static ssize_t f_phonet_attr_show(struct config_item *item,
-                               struct configfs_attribute *attr,
-                               char *page)
-{
-       struct f_phonet_opts *opts = to_f_phonet_opts(item);
-       struct f_phonet_opts_attribute *f_phonet_opts_attr =
-               container_of(attr, struct f_phonet_opts_attribute, attr);
-       ssize_t ret = 0;
-
-       if (f_phonet_opts_attr->show)
-               ret = f_phonet_opts_attr->show(opts, page);
-       return ret;
-}
-
 static void phonet_attr_release(struct config_item *item)
 {
        struct f_phonet_opts *opts = to_f_phonet_opts(item);
@@ -607,19 +592,17 @@ static void phonet_attr_release(struct config_item *item)
 
 static struct configfs_item_operations phonet_item_ops = {
        .release                = phonet_attr_release,
-       .show_attribute         = f_phonet_attr_show,
 };
 
-static ssize_t f_phonet_ifname_show(struct f_phonet_opts *opts, char *page)
+static ssize_t f_phonet_ifname_show(struct config_item *item, char *page)
 {
-       return gether_get_ifname(opts->net, page, PAGE_SIZE);
+       return gether_get_ifname(to_f_phonet_opts(item)->net, page, PAGE_SIZE);
 }
 
-static struct f_phonet_opts_attribute f_phonet_ifname =
-       __CONFIGFS_ATTR_RO(ifname, f_phonet_ifname_show);
+CONFIGFS_ATTR_RO(f_phonet_, ifname);
 
 static struct configfs_attribute *phonet_attrs[] = {
-       &f_phonet_ifname.attr,
+       &f_phonet_attr_ifname,
        NULL,
 };
 
index 7fb3209ed52c31c662b24b1799e78ff9a4d38700..0fbfb2b2aa08b3ade8e4b487d012188687b29e05 100644 (file)
@@ -1146,9 +1146,6 @@ static inline struct f_printer_opts
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_printer_opts);
-CONFIGFS_ATTR_OPS(f_printer_opts);
-
 static void printer_attr_release(struct config_item *item)
 {
        struct f_printer_opts *opts = to_f_printer_opts(item);
@@ -1158,13 +1155,12 @@ static void printer_attr_release(struct config_item *item)
 
 static struct configfs_item_operations printer_item_ops = {
        .release        = printer_attr_release,
-       .show_attribute = f_printer_opts_attr_show,
-       .store_attribute = f_printer_opts_attr_store,
 };
 
-static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
                                              char *page)
 {
+       struct f_printer_opts *opts = to_f_printer_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1174,9 +1170,10 @@ static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
        return result;
 }
 
-static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_store(struct config_item *item,
                                               const char *page, size_t len)
 {
+       struct f_printer_opts *opts = to_f_printer_opts(item);
        int result, l;
 
        mutex_lock(&opts->lock);
@@ -1189,14 +1186,12 @@ static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
        return result;
 }
 
-static struct f_printer_opts_attribute f_printer_opts_pnp_string =
-       __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR,
-                       f_printer_opts_pnp_string_show,
-                       f_printer_opts_pnp_string_store);
+CONFIGFS_ATTR(f_printer_opts_, pnp_string);
 
-static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_show(struct config_item *item,
                                         char *page)
 {
+       struct f_printer_opts *opts = to_f_printer_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1206,9 +1201,10 @@ static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
        return result;
 }
 
-static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_store(struct config_item *item,
                                          const char *page, size_t len)
 {
+       struct f_printer_opts *opts = to_f_printer_opts(item);
        int ret;
        u16 num;
 
@@ -1229,13 +1225,11 @@ static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
        return ret;
 }
 
-static struct f_printer_opts_attribute f_printer_opts_q_len =
-       __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show,
-                       f_printer_opts_q_len_store);
+CONFIGFS_ATTR(f_printer_opts_, q_len);
 
 static struct configfs_attribute *printer_attrs[] = {
-       &f_printer_opts_pnp_string.attr,
-       &f_printer_opts_q_len.attr,
+       &f_printer_opts_attr_pnp_string,
+       &f_printer_opts_attr_q_len,
        NULL,
 };
 
index fd301ed9e294fa480ad0336fc17833e772611765..e587767e374cbc2fbae3b02879b5358c38d48e69 100644 (file)
@@ -864,10 +864,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
 
 static struct configfs_attribute *rndis_attrs[] = {
-       &f_rndis_opts_dev_addr.attr,
-       &f_rndis_opts_host_addr.attr,
-       &f_rndis_opts_qmult.attr,
-       &f_rndis_opts_ifname.attr,
+       &rndis_opts_attr_dev_addr,
+       &rndis_opts_attr_host_addr,
+       &rndis_opts_attr_qmult,
+       &rndis_opts_attr_ifname,
        NULL,
 };
 
index ba705e047d7e0fca31ce8a2ede4d67f595efb5ca..6bb44d613baba28106d31023d337edf6367b9333 100644 (file)
@@ -258,22 +258,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_serial_attr_show(struct config_item *item,
-                                 struct configfs_attribute *attr,
-                                 char *page)
-{
-       struct f_serial_opts *opts = to_f_serial_opts(item);
-       struct f_serial_opts_attribute *f_serial_opts_attr =
-               container_of(attr, struct f_serial_opts_attribute, attr);
-       ssize_t ret = 0;
-
-       if (f_serial_opts_attr->show)
-               ret = f_serial_opts_attr->show(opts, page);
-
-       return ret;
-}
-
 static void serial_attr_release(struct config_item *item)
 {
        struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -283,19 +267,17 @@ static void serial_attr_release(struct config_item *item)
 
 static struct configfs_item_operations serial_item_ops = {
        .release        = serial_attr_release,
-       .show_attribute = f_serial_attr_show,
 };
 
-static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_serial_port_num_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", opts->port_num);
+       return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
 }
 
-static struct f_serial_opts_attribute f_serial_port_num =
-       __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+CONFIGFS_ATTR_RO(f_serial_, port_num);
 
 static struct configfs_attribute *acm_attrs[] = {
-       &f_serial_port_num.attr,
+       &f_serial_attr_port_num,
        NULL,
 };
 
index d7646d3acd63ecb4aa87362e069b54faff909844..9f3ced62d9162c991c03b0db68d10fd0cbe06ea9 100644 (file)
@@ -889,9 +889,6 @@ static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_ss_opts);
-CONFIGFS_ATTR_OPS(f_ss_opts);
-
 static void ss_attr_release(struct config_item *item)
 {
        struct f_ss_opts *ss_opts = to_f_ss_opts(item);
@@ -901,12 +898,11 @@ static void ss_attr_release(struct config_item *item)
 
 static struct configfs_item_operations ss_item_ops = {
        .release                = ss_attr_release,
-       .show_attribute         = f_ss_opts_attr_show,
-       .store_attribute        = f_ss_opts_attr_store,
 };
 
-static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_pattern_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -916,9 +912,10 @@ static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_pattern_store(struct config_item *item,
                                       const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u8 num;
 
@@ -944,13 +941,11 @@ static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_pattern =
-       __CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR,
-                       f_ss_opts_pattern_show,
-                       f_ss_opts_pattern_store);
+CONFIGFS_ATTR(f_ss_opts_, pattern);
 
-static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_interval_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -960,9 +955,10 @@ static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_interval_store(struct config_item *item,
                                       const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u8 num;
 
@@ -988,13 +984,11 @@ static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_isoc_interval =
-       __CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR,
-                       f_ss_opts_isoc_interval_show,
-                       f_ss_opts_isoc_interval_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_interval);
 
-static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_maxpacket_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1004,9 +998,10 @@ static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_maxpacket_store(struct config_item *item,
                                       const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u16 num;
 
@@ -1032,13 +1027,11 @@ static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket =
-       __CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR,
-                       f_ss_opts_isoc_maxpacket_show,
-                       f_ss_opts_isoc_maxpacket_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_maxpacket);
 
-static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_mult_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1048,9 +1041,10 @@ static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_mult_store(struct config_item *item,
                                       const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u8 num;
 
@@ -1076,13 +1070,11 @@ static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_isoc_mult =
-       __CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR,
-                       f_ss_opts_isoc_mult_show,
-                       f_ss_opts_isoc_mult_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_mult);
 
-static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_isoc_maxburst_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1092,9 +1084,10 @@ static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_isoc_maxburst_store(struct config_item *item,
                                       const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u8 num;
 
@@ -1120,13 +1113,11 @@ static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst =
-       __CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR,
-                       f_ss_opts_isoc_maxburst_show,
-                       f_ss_opts_isoc_maxburst_store);
+CONFIGFS_ATTR(f_ss_opts_, isoc_maxburst);
 
-static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
+static ssize_t f_ss_opts_bulk_buflen_show(struct config_item *item, char *page)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int result;
 
        mutex_lock(&opts->lock);
@@ -1136,9 +1127,10 @@ static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
        return result;
 }
 
-static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
+static ssize_t f_ss_opts_bulk_buflen_store(struct config_item *item,
                                           const char *page, size_t len)
 {
+       struct f_ss_opts *opts = to_f_ss_opts(item);
        int ret;
        u32 num;
 
@@ -1159,18 +1151,15 @@ static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts,
        return ret;
 }
 
-static struct f_ss_opts_attribute f_ss_opts_bulk_buflen =
-       __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
-                       f_ss_opts_bulk_buflen_show,
-                       f_ss_opts_bulk_buflen_store);
+CONFIGFS_ATTR(f_ss_opts_, bulk_buflen);
 
 static struct configfs_attribute *ss_attrs[] = {
-       &f_ss_opts_pattern.attr,
-       &f_ss_opts_isoc_interval.attr,
-       &f_ss_opts_isoc_maxpacket.attr,
-       &f_ss_opts_isoc_mult.attr,
-       &f_ss_opts_isoc_maxburst.attr,
-       &f_ss_opts_bulk_buflen.attr,
+       &f_ss_opts_attr_pattern,
+       &f_ss_opts_attr_isoc_interval,
+       &f_ss_opts_attr_isoc_maxpacket,
+       &f_ss_opts_attr_isoc_mult,
+       &f_ss_opts_attr_isoc_maxburst,
+       &f_ss_opts_attr_bulk_buflen,
        NULL,
 };
 
index 2e66e624e6e13dfed2fde71fff294a10a986bb7a..829c78de9ebac728919784951b89d05d7d942361 100644 (file)
@@ -405,10 +405,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether);
 USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether);
 
 static struct configfs_attribute *gether_attrs[] = {
-       &f_gether_opts_dev_addr.attr,
-       &f_gether_opts_host_addr.attr,
-       &f_gether_opts_qmult.attr,
-       &f_gether_opts_ifname.attr,
+       &gether_opts_attr_dev_addr,
+       &gether_opts_attr_host_addr,
+       &gether_opts_attr_qmult,
+       &gether_opts_attr_ifname,
        NULL,
 };
 
index 8ee701924d29d0c5ad27edfed1b3e23c15b5c3e7..6a2346b99f5591911f92200d68e880ff3b2e5d18 100644 (file)
@@ -769,9 +769,6 @@ static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_uac1_opts);
-CONFIGFS_ATTR_OPS(f_uac1_opts);
-
 static void f_uac1_attr_release(struct config_item *item)
 {
        struct f_uac1_opts *opts = to_f_uac1_opts(item);
@@ -781,14 +778,13 @@ static void f_uac1_attr_release(struct config_item *item)
 
 static struct configfs_item_operations f_uac1_item_ops = {
        .release        = f_uac1_attr_release,
-       .show_attribute = f_uac1_opts_attr_show,
-       .store_attribute = f_uac1_opts_attr_store,
 };
 
 #define UAC1_INT_ATTRIBUTE(name)                                       \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts,     \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item,     \
                                         char *page)                    \
 {                                                                      \
+       struct f_uac1_opts *opts = to_f_uac1_opts(item);                \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -798,9 +794,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts,    \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item,            \
                                          const char *page, size_t len) \
 {                                                                      \
+       struct f_uac1_opts *opts = to_f_uac1_opts(item);                \
        int ret;                                                        \
        u32 num;                                                        \
                                                                        \
@@ -822,19 +819,17 @@ end:                                                                      \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_uac1_opts_attribute f_uac1_opts_##name =               \
-       __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR,                        \
-                       f_uac1_opts_##name##_show,                      \
-                       f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
 
 UAC1_INT_ATTRIBUTE(req_buf_size);
 UAC1_INT_ATTRIBUTE(req_count);
 UAC1_INT_ATTRIBUTE(audio_buf_size);
 
 #define UAC1_STR_ATTRIBUTE(name)                                       \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts,     \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item,     \
                                         char *page)                    \
 {                                                                      \
+       struct f_uac1_opts *opts = to_f_uac1_opts(item);                \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -844,9 +839,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts,    \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item,    \
                                          const char *page, size_t len) \
 {                                                                      \
+       struct f_uac1_opts *opts = to_f_uac1_opts(item);                \
        int ret = -EBUSY;                                               \
        char *tmp;                                                      \
                                                                        \
@@ -870,22 +866,19 @@ end:                                                                      \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_uac1_opts_attribute f_uac1_opts_##name =               \
-       __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR,                        \
-                       f_uac1_opts_##name##_show,                      \
-                       f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
 
 UAC1_STR_ATTRIBUTE(fn_play);
 UAC1_STR_ATTRIBUTE(fn_cap);
 UAC1_STR_ATTRIBUTE(fn_cntl);
 
 static struct configfs_attribute *f_uac1_attrs[] = {
-       &f_uac1_opts_req_buf_size.attr,
-       &f_uac1_opts_req_count.attr,
-       &f_uac1_opts_audio_buf_size.attr,
-       &f_uac1_opts_fn_play.attr,
-       &f_uac1_opts_fn_cap.attr,
-       &f_uac1_opts_fn_cntl.attr,
+       &f_uac1_opts_attr_req_buf_size,
+       &f_uac1_opts_attr_req_count,
+       &f_uac1_opts_attr_audio_buf_size,
+       &f_uac1_opts_attr_fn_play,
+       &f_uac1_opts_attr_fn_cap,
+       &f_uac1_opts_attr_fn_cntl,
        NULL,
 };
 
index 63336e269898d07ac42c2ab66117c9aaed2ae142..044ca79d3cb5d3b8a4764e27c1a1749caa43c971 100644 (file)
@@ -1439,9 +1439,6 @@ static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_uac2_opts);
-CONFIGFS_ATTR_OPS(f_uac2_opts);
-
 static void f_uac2_attr_release(struct config_item *item)
 {
        struct f_uac2_opts *opts = to_f_uac2_opts(item);
@@ -1451,14 +1448,13 @@ static void f_uac2_attr_release(struct config_item *item)
 
 static struct configfs_item_operations f_uac2_item_ops = {
        .release        = f_uac2_attr_release,
-       .show_attribute = f_uac2_opts_attr_show,
-       .store_attribute = f_uac2_opts_attr_store,
 };
 
 #define UAC2_ATTRIBUTE(name)                                           \
-static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts,     \
+static ssize_t f_uac2_opts_##name##_show(struct config_item *item,     \
                                         char *page)                    \
 {                                                                      \
+       struct f_uac2_opts *opts = to_f_uac2_opts(item);                \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -1468,9 +1464,10 @@ static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts,       \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t f_uac2_opts_##name##_store(struct f_uac2_opts *opts,    \
+static ssize_t f_uac2_opts_##name##_store(struct config_item *item,    \
                                          const char *page, size_t len) \
 {                                                                      \
+       struct f_uac2_opts *opts = to_f_uac2_opts(item);                \
        int ret;                                                        \
        u32 num;                                                        \
                                                                        \
@@ -1492,10 +1489,7 @@ end:                                                                     \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_uac2_opts_attribute f_uac2_opts_##name =               \
-       __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR,                        \
-                       f_uac2_opts_##name##_show,                      \
-                       f_uac2_opts_##name##_store)
+CONFIGFS_ATTR(f_uac2_opts_, name)
 
 UAC2_ATTRIBUTE(p_chmask);
 UAC2_ATTRIBUTE(p_srate);
@@ -1505,12 +1499,12 @@ UAC2_ATTRIBUTE(c_srate);
 UAC2_ATTRIBUTE(c_ssize);
 
 static struct configfs_attribute *f_uac2_attrs[] = {
-       &f_uac2_opts_p_chmask.attr,
-       &f_uac2_opts_p_srate.attr,
-       &f_uac2_opts_p_ssize.attr,
-       &f_uac2_opts_c_chmask.attr,
-       &f_uac2_opts_c_srate.attr,
-       &f_uac2_opts_c_ssize.attr,
+       &f_uac2_opts_attr_p_chmask,
+       &f_uac2_opts_attr_p_srate,
+       &f_uac2_opts_attr_p_ssize,
+       &f_uac2_opts_attr_c_chmask,
+       &f_uac2_opts_attr_c_srate,
+       &f_uac2_opts_attr_c_ssize,
        NULL,
 };
 
index bcbd30146cfde6a3ff74b252621ee6b0b3e1c764..4f47289fcf7cee45e93e8f9171a19390f91ee49f 100644 (file)
@@ -17,9 +17,6 @@
 #define __U_ETHER_CONFIGFS_H
 
 #define USB_ETHERNET_CONFIGFS_ITEM(_f_)                                        \
-       CONFIGFS_ATTR_STRUCT(f_##_f_##_opts);                           \
-       CONFIGFS_ATTR_OPS(f_##_f_##_opts);                              \
-                                                                       \
        static void _f_##_attr_release(struct config_item *item)        \
        {                                                               \
                struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                                                                        \
        static struct configfs_item_operations _f_##_item_ops = {       \
                .release        = _f_##_attr_release,                   \
-               .show_attribute = f_##_f_##_opts_attr_show,             \
-               .store_attribute = f_##_f_##_opts_attr_store,           \
        }
 
 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_)                  \
-       static ssize_t _f_##_opts_dev_addr_show(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \
                                                char *page)             \
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                int result;                                             \
                                                                        \
                mutex_lock(&opts->lock);                                \
                return result;                                          \
        }                                                               \
                                                                        \
-       static ssize_t _f_##_opts_dev_addr_store(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \
                                                 const char *page, size_t len)\
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                int ret;                                                \
                                                                        \
                mutex_lock(&opts->lock);                                \
                return ret;                                             \
        }                                                               \
                                                                        \
-       static struct f_##_f_##_opts_attribute f_##_f_##_opts_dev_addr = \
-               __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR,            \
-                               _f_##_opts_dev_addr_show,               \
-                               _f_##_opts_dev_addr_store)
+       CONFIGFS_ATTR(_f_##_opts_, dev_addr)
 
 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_)                 \
-       static ssize_t _f_##_opts_host_addr_show(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \
                                                 char *page)            \
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                int result;                                             \
                                                                        \
                mutex_lock(&opts->lock);                                \
                return result;                                          \
        }                                                               \
                                                                        \
-       static ssize_t _f_##_opts_host_addr_store(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \
                                                  const char *page, size_t len)\
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                int ret;                                                \
                                                                        \
                mutex_lock(&opts->lock);                                \
                return ret;                                             \
        }                                                               \
                                                                        \
-       static struct f_##_f_##_opts_attribute f_##_f_##_opts_host_addr = \
-               __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR,           \
-                               _f_##_opts_host_addr_show,              \
-                               _f_##_opts_host_addr_store)
+       CONFIGFS_ATTR(_f_##_opts_, host_addr)
 
 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_)                     \
-       static ssize_t _f_##_opts_qmult_show(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_qmult_show(struct config_item *item,  \
                                             char *page)                \
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                unsigned qmult;                                         \
                                                                        \
                mutex_lock(&opts->lock);                                \
                return sprintf(page, "%d", qmult);                      \
        }                                                               \
                                                                        \
-       static ssize_t _f_##_opts_qmult_store(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_qmult_store(struct config_item *item, \
                                              const char *page, size_t len)\
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                u8 val;                                                 \
                int ret;                                                \
                                                                        \
@@ -140,15 +135,13 @@ out:                                                                      \
                return ret;                                             \
        }                                                               \
                                                                        \
-       static struct f_##_f_##_opts_attribute f_##_f_##_opts_qmult =   \
-               __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR,               \
-                               _f_##_opts_qmult_show,          \
-                               _f_##_opts_qmult_store)
+       CONFIGFS_ATTR(_f_##_opts_, qmult)
 
 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_)                    \
-       static ssize_t _f_##_opts_ifname_show(struct f_##_f_##_opts *opts, \
+       static ssize_t _f_##_opts_ifname_show(struct config_item *item, \
                                              char *page)               \
        {                                                               \
+               struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item);  \
                int ret;                                                \
                                                                        \
                mutex_lock(&opts->lock);                                \
@@ -158,7 +151,6 @@ out:                                                                        \
                return ret;                                             \
        }                                                               \
                                                                        \
-       static struct f_##_f_##_opts_attribute f_##_f_##_opts_ifname =  \
-               __CONFIGFS_ATTR_RO(ifname, _f_##_opts_ifname_show)
+       CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
 
 #endif /* __U_ETHER_CONFIGFS_H */
index 3c0467bcb14fd9a3ccc15104a22e24f461781b4d..289ebca316d3f4ab0e136a14858bb7275eee53c0 100644 (file)
 
 #define UVCG_STREAMING_CONTROL_SIZE    1
 
-#define CONFIGFS_ATTR_OPS_RO(_item)                                    \
-static ssize_t _item##_attr_show(struct config_item *item,             \
-                                struct configfs_attribute *attr,       \
-                                char *page)                            \
-{                                                                      \
-       struct _item *_item = to_##_item(item);                         \
-       struct _item##_attribute *_item##_attr =                        \
-               container_of(attr, struct _item##_attribute, attr);     \
-       ssize_t ret = 0;                                                \
-                                                                       \
-       if (_item##_attr->show)                                         \
-               ret = _item##_attr->show(_item, page);                  \
-       return ret;                                                     \
+#define UVC_ATTR(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+       .ca_name        = __stringify(aname),                           \
+       .ca_mode        = S_IRUGO,                                      \
+       .ca_owner       = THIS_MODULE,                                  \
+       .show           = prefix##cname##_show,                         \
+       .store          = prefix##cname##_store,                        \
+}
+
+#define UVC_ATTR_RO(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+       .ca_name        = __stringify(aname),                           \
+       .ca_mode        = S_IRUGO,                                      \
+       .ca_owner       = THIS_MODULE,                                  \
+       .show           = prefix##cname##_show,                         \
 }
 
 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
@@ -48,18 +50,11 @@ static struct uvcg_control_header *to_uvcg_control_header(struct config_item *it
        return container_of(item, struct uvcg_control_header, item);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_control_header);
-CONFIGFS_ATTR_OPS(uvcg_control_header);
-
-static struct configfs_item_operations uvcg_control_header_item_ops = {
-       .show_attribute         = uvcg_control_header_attr_show,
-       .store_attribute        = uvcg_control_header_attr_store,
-};
-
 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit)        \
 static ssize_t uvcg_control_header_##cname##_show(                     \
-       struct uvcg_control_header *ch, char *page)                     \
+       struct config_item *item, char *page)                   \
 {                                                                      \
+       struct uvcg_control_header *ch = to_uvcg_control_header(item);  \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -79,9 +74,10 @@ static ssize_t uvcg_control_header_##cname##_show(                   \
 }                                                                      \
                                                                        \
 static ssize_t                                                         \
-uvcg_control_header_##cname##_store(struct uvcg_control_header *ch,    \
+uvcg_control_header_##cname##_store(struct config_item *item,          \
                           const char *page, size_t len)                \
 {                                                                      \
+       struct uvcg_control_header *ch = to_uvcg_control_header(item);  \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -115,11 +111,7 @@ end:                                                                       \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct uvcg_control_header_attribute                            \
-       uvcg_control_header_##cname =                                   \
-       __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR,                       \
-                       uvcg_control_header_##cname##_show,             \
-                       uvcg_control_header_##cname##_store)
+UVC_ATTR(uvcg_control_header_, cname, aname)
 
 UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
                   0xffff);
@@ -130,13 +122,12 @@ UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
 #undef UVCG_CTRL_HDR_ATTR
 
 static struct configfs_attribute *uvcg_control_header_attrs[] = {
-       &uvcg_control_header_bcd_uvc.attr,
-       &uvcg_control_header_dw_clock_frequency.attr,
+       &uvcg_control_header_attr_bcd_uvc,
+       &uvcg_control_header_attr_dw_clock_frequency,
        NULL,
 };
 
 static struct config_item_type uvcg_control_header_type = {
-       .ct_item_ops    = &uvcg_control_header_item_ops,
        .ct_attrs       = uvcg_control_header_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -196,17 +187,11 @@ static inline struct uvcg_default_processing
                            struct uvcg_default_processing, group);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_default_processing);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_processing);
-
-static struct configfs_item_operations uvcg_default_processing_item_ops = {
-       .show_attribute         = uvcg_default_processing_attr_show,
-};
-
 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)               \
 static ssize_t uvcg_default_processing_##cname##_show(                 \
-       struct uvcg_default_processing *dp, char *page)                 \
+       struct config_item *item, char *page)                           \
 {                                                                      \
+       struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;        \
@@ -227,9 +212,7 @@ static ssize_t uvcg_default_processing_##cname##_show(                      \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_default_processing_attribute                                \
-       uvcg_default_processing_##cname =                               \
-       __CONFIGFS_ATTR_RO(aname, uvcg_default_processing_##cname##_show)
+UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -243,8 +226,9 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
 #undef UVCG_DEFAULT_PROCESSING_ATTR
 
 static ssize_t uvcg_default_processing_bm_controls_show(
-       struct uvcg_default_processing *dp, char *page)
+       struct config_item *item, char *page)
 {
+       struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
@@ -270,22 +254,18 @@ static ssize_t uvcg_default_processing_bm_controls_show(
        return result;
 }
 
-static struct uvcg_default_processing_attribute
-       uvcg_default_processing_bm_controls =
-       __CONFIGFS_ATTR_RO(bmControls,
-               uvcg_default_processing_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
 
 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
-       &uvcg_default_processing_b_unit_id.attr,
-       &uvcg_default_processing_b_source_id.attr,
-       &uvcg_default_processing_w_max_multiplier.attr,
-       &uvcg_default_processing_bm_controls.attr,
-       &uvcg_default_processing_i_processing.attr,
+       &uvcg_default_processing_attr_b_unit_id,
+       &uvcg_default_processing_attr_b_source_id,
+       &uvcg_default_processing_attr_w_max_multiplier,
+       &uvcg_default_processing_attr_bm_controls,
+       &uvcg_default_processing_attr_i_processing,
        NULL,
 };
 
 static struct config_item_type uvcg_default_processing_type = {
-       .ct_item_ops    = &uvcg_default_processing_item_ops,
        .ct_attrs       = uvcg_default_processing_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -318,17 +298,11 @@ static inline struct uvcg_default_camera
                            struct uvcg_default_camera, group);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_default_camera);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_camera);
-
-static struct configfs_item_operations uvcg_default_camera_item_ops = {
-       .show_attribute         = uvcg_default_camera_attr_show,
-};
-
 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv)                   \
 static ssize_t uvcg_default_camera_##cname##_show(                     \
-       struct uvcg_default_camera *dc, char *page)                     \
+       struct config_item *item, char *page)                           \
 {                                                                      \
+       struct uvcg_default_camera *dc = to_uvcg_default_camera(item);  \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;        \
@@ -351,9 +325,7 @@ static ssize_t uvcg_default_camera_##cname##_show(                  \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_default_camera_attribute                            \
-       uvcg_default_camera_##cname =                                   \
-       __CONFIGFS_ATTR_RO(aname, uvcg_default_camera_##cname##_show)
+UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -373,8 +345,9 @@ UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
 #undef UVCG_DEFAULT_CAMERA_ATTR
 
 static ssize_t uvcg_default_camera_bm_controls_show(
-       struct uvcg_default_camera *dc, char *page)
+       struct config_item *item, char *page)
 {
+       struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
@@ -400,24 +373,21 @@ static ssize_t uvcg_default_camera_bm_controls_show(
        return result;
 }
 
-static struct uvcg_default_camera_attribute
-       uvcg_default_camera_bm_controls =
-       __CONFIGFS_ATTR_RO(bmControls, uvcg_default_camera_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
 
 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
-       &uvcg_default_camera_b_terminal_id.attr,
-       &uvcg_default_camera_w_terminal_type.attr,
-       &uvcg_default_camera_b_assoc_terminal.attr,
-       &uvcg_default_camera_i_terminal.attr,
-       &uvcg_default_camera_w_objective_focal_length_min.attr,
-       &uvcg_default_camera_w_objective_focal_length_max.attr,
-       &uvcg_default_camera_w_ocular_focal_length.attr,
-       &uvcg_default_camera_bm_controls.attr,
+       &uvcg_default_camera_attr_b_terminal_id,
+       &uvcg_default_camera_attr_w_terminal_type,
+       &uvcg_default_camera_attr_b_assoc_terminal,
+       &uvcg_default_camera_attr_i_terminal,
+       &uvcg_default_camera_attr_w_objective_focal_length_min,
+       &uvcg_default_camera_attr_w_objective_focal_length_max,
+       &uvcg_default_camera_attr_w_ocular_focal_length,
+       &uvcg_default_camera_attr_bm_controls,
        NULL,
 };
 
 static struct config_item_type uvcg_default_camera_type = {
-       .ct_item_ops    = &uvcg_default_camera_item_ops,
        .ct_attrs       = uvcg_default_camera_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -450,17 +420,11 @@ static inline struct uvcg_default_output
                            struct uvcg_default_output, group);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_default_output);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_output);
-
-static struct configfs_item_operations uvcg_default_output_item_ops = {
-       .show_attribute         = uvcg_default_output_attr_show,
-};
-
 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv)                   \
 static ssize_t uvcg_default_output_##cname##_show(                     \
-       struct uvcg_default_output *dout, char *page)                   \
+       struct config_item *item, char *page)                   \
 {                                                                      \
+       struct uvcg_default_output *dout = to_uvcg_default_output(item); \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex;      \
@@ -483,9 +447,7 @@ static ssize_t uvcg_default_output_##cname##_show(                  \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_default_output_attribute                            \
-       uvcg_default_output_##cname =                                   \
-       __CONFIGFS_ATTR_RO(aname, uvcg_default_output_##cname##_show)
+UVC_ATTR_RO(uvcg_default_output_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -500,16 +462,15 @@ UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
 #undef UVCG_DEFAULT_OUTPUT_ATTR
 
 static struct configfs_attribute *uvcg_default_output_attrs[] = {
-       &uvcg_default_output_b_terminal_id.attr,
-       &uvcg_default_output_w_terminal_type.attr,
-       &uvcg_default_output_b_assoc_terminal.attr,
-       &uvcg_default_output_b_source_id.attr,
-       &uvcg_default_output_i_terminal.attr,
+       &uvcg_default_output_attr_b_terminal_id,
+       &uvcg_default_output_attr_w_terminal_type,
+       &uvcg_default_output_attr_b_assoc_terminal,
+       &uvcg_default_output_attr_b_source_id,
+       &uvcg_default_output_attr_i_terminal,
        NULL,
 };
 
 static struct config_item_type uvcg_default_output_type = {
-       .ct_item_ops    = &uvcg_default_output_item_ops,
        .ct_attrs       = uvcg_default_output_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -800,9 +761,6 @@ static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item
        return container_of(item, struct uvcg_streaming_header, item);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_streaming_header);
-CONFIGFS_ATTR_OPS(uvcg_streaming_header);
-
 static int uvcg_streaming_header_allow_link(struct config_item *src,
                                            struct config_item *target)
 {
@@ -893,16 +851,15 @@ static int uvcg_streaming_header_drop_link(struct config_item *src,
 }
 
 static struct configfs_item_operations uvcg_streaming_header_item_ops = {
-       .show_attribute         = uvcg_streaming_header_attr_show,
-       .store_attribute        = uvcg_streaming_header_attr_store,
        .allow_link             = uvcg_streaming_header_allow_link,
        .drop_link              = uvcg_streaming_header_drop_link,
 };
 
 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv)                 \
 static ssize_t uvcg_streaming_header_##cname##_show(                   \
-       struct uvcg_streaming_header *sh, char *page)                   \
+       struct config_item *item, char *page)                   \
 {                                                                      \
+       struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
@@ -921,9 +878,7 @@ static ssize_t uvcg_streaming_header_##cname##_show(                        \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_streaming_header_attribute                          \
-       uvcg_streaming_header_##cname =                                 \
-       __CONFIGFS_ATTR_RO(aname, uvcg_streaming_header_##cname##_show)
+UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -939,11 +894,11 @@ UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
 #undef UVCG_STREAMING_HEADER_ATTR
 
 static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
-       &uvcg_streaming_header_bm_info.attr,
-       &uvcg_streaming_header_b_terminal_link.attr,
-       &uvcg_streaming_header_b_still_capture_method.attr,
-       &uvcg_streaming_header_b_trigger_support.attr,
-       &uvcg_streaming_header_b_trigger_usage.attr,
+       &uvcg_streaming_header_attr_bm_info,
+       &uvcg_streaming_header_attr_b_terminal_link,
+       &uvcg_streaming_header_attr_b_still_capture_method,
+       &uvcg_streaming_header_attr_b_trigger_support,
+       &uvcg_streaming_header_attr_b_trigger_usage,
        NULL,
 };
 
@@ -1022,17 +977,10 @@ static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
        return container_of(item, struct uvcg_frame, item);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_frame);
-CONFIGFS_ATTR_OPS(uvcg_frame);
-
-static struct configfs_item_operations uvcg_frame_item_ops = {
-       .show_attribute         = uvcg_frame_attr_show,
-       .store_attribute        = uvcg_frame_attr_store,
-};
-
 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
-static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
+static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
 {                                                                      \
+       struct uvcg_frame *f = to_uvcg_frame(item);                     \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
@@ -1051,9 +999,10 @@ static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
        return result;                                                  \
 }                                                                      \
                                                                        \
-static ssize_t  uvcg_frame_##cname##_store(struct uvcg_frame *f,       \
+static ssize_t  uvcg_frame_##cname##_store(struct config_item *item,   \
                                           const char *page, size_t len)\
 {                                                                      \
+       struct uvcg_frame *f = to_uvcg_frame(item);                     \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct uvcg_format *fmt;                                        \
@@ -1085,11 +1034,7 @@ end:                                                                     \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct uvcg_frame_attribute                                     \
-       uvcg_frame_##cname =                                            \
-       __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR,                       \
-                       uvcg_frame_##cname##_show,                      \
-                       uvcg_frame_##cname##_store)
+UVC_ATTR(uvcg_frame_, cname, aname);
 
 #define noop_conversion(x) (x)
 
@@ -1108,9 +1053,10 @@ UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
 
 #undef UVCG_FRAME_ATTR
 
-static ssize_t uvcg_frame_dw_frame_interval_show(struct uvcg_frame *frm,
+static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
                                                 char *page)
 {
+       struct uvcg_frame *frm = to_uvcg_frame(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
@@ -1185,9 +1131,10 @@ static int __uvcg_iter_frm_intrv(const char *page, size_t len,
        return 0;
 }
 
-static ssize_t uvcg_frame_dw_frame_interval_store(struct uvcg_frame *ch,
+static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
                                                  const char *page, size_t len)
 {
+       struct uvcg_frame *ch = to_uvcg_frame(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct uvcg_format *fmt;
@@ -1234,26 +1181,21 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct uvcg_frame *ch,
        return ret;
 }
 
-static struct uvcg_frame_attribute
-       uvcg_frame_dw_frame_interval =
-       __CONFIGFS_ATTR(dwFrameInterval, S_IRUGO | S_IWUSR,
-                       uvcg_frame_dw_frame_interval_show,
-                       uvcg_frame_dw_frame_interval_store);
+UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
 
 static struct configfs_attribute *uvcg_frame_attrs[] = {
-       &uvcg_frame_bm_capabilities.attr,
-       &uvcg_frame_w_width.attr,
-       &uvcg_frame_w_height.attr,
-       &uvcg_frame_dw_min_bit_rate.attr,
-       &uvcg_frame_dw_max_bit_rate.attr,
-       &uvcg_frame_dw_max_video_frame_buffer_size.attr,
-       &uvcg_frame_dw_default_frame_interval.attr,
-       &uvcg_frame_dw_frame_interval.attr,
+       &uvcg_frame_attr_bm_capabilities,
+       &uvcg_frame_attr_w_width,
+       &uvcg_frame_attr_w_height,
+       &uvcg_frame_attr_dw_min_bit_rate,
+       &uvcg_frame_attr_dw_max_bit_rate,
+       &uvcg_frame_attr_dw_max_video_frame_buffer_size,
+       &uvcg_frame_attr_dw_default_frame_interval,
+       &uvcg_frame_attr_dw_frame_interval,
        NULL,
 };
 
 static struct config_item_type uvcg_frame_type = {
-       .ct_item_ops    = &uvcg_frame_item_ops,
        .ct_attrs       = uvcg_frame_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -1333,22 +1275,15 @@ static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
                struct uvcg_uncompressed, fmt);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_uncompressed);
-CONFIGFS_ATTR_OPS(uvcg_uncompressed);
-
-static struct configfs_item_operations uvcg_uncompressed_item_ops = {
-       .show_attribute         = uvcg_uncompressed_attr_show,
-       .store_attribute        = uvcg_uncompressed_attr_store,
-};
-
 static struct configfs_group_operations uvcg_uncompressed_group_ops = {
        .make_item              = uvcg_frame_make,
        .drop_item              = uvcg_frame_drop,
 };
 
-static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
                                                        char *page)
 {
+       struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1367,9 +1302,10 @@ static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
        return sizeof(ch->desc.guidFormat);
 }
 
-static ssize_t uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
                                                   const char *page, size_t len)
 {
+       struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
        struct f_uvc_opts *opts;
        struct config_item *opts_item;
        struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1396,16 +1332,13 @@ static ssize_t uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed *ch,
        return ret;
 }
 
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_guid_format =
-       __CONFIGFS_ATTR(guidFormat, S_IRUGO | S_IWUSR,
-                       uvcg_uncompressed_guid_format_show,
-                       uvcg_uncompressed_guid_format_store);
-
+UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
 
 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv)                  \
 static ssize_t uvcg_uncompressed_##cname##_show(                       \
-       struct uvcg_uncompressed *u, char *page)                        \
+       struct config_item *item, char *page)                           \
 {                                                                      \
+       struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);       \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1424,14 +1357,13 @@ static ssize_t uvcg_uncompressed_##cname##_show(                        \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_uncompressed_attribute                              \
-       uvcg_uncompressed_##cname =                                     \
-       __CONFIGFS_ATTR_RO(aname, uvcg_uncompressed_##cname##_show)
+UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
 
 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv)                     \
 static ssize_t uvcg_uncompressed_##cname##_show(                       \
-       struct uvcg_uncompressed *u, char *page)                        \
+       struct config_item *item, char *page)                           \
 {                                                                      \
+       struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);       \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1451,9 +1383,10 @@ static ssize_t uvcg_uncompressed_##cname##_show(                 \
 }                                                                      \
                                                                        \
 static ssize_t                                                         \
-uvcg_uncompressed_##cname##_store(struct uvcg_uncompressed *u,         \
+uvcg_uncompressed_##cname##_store(struct config_item *item,            \
                                    const char *page, size_t len)       \
 {                                                                      \
+       struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);       \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1487,11 +1420,7 @@ end:                                                                     \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct uvcg_uncompressed_attribute                              \
-       uvcg_uncompressed_##cname =                                     \
-       __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR,                       \
-                       uvcg_uncompressed_##cname##_show,               \
-                       uvcg_uncompressed_##cname##_store)
+UVC_ATTR(uvcg_uncompressed_, cname, aname);
 
 #define identity_conv(x) (x)
 
@@ -1508,36 +1437,34 @@ UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
 #undef UVCG_UNCOMPRESSED_ATTR_RO
 
 static inline ssize_t
-uvcg_uncompressed_bma_controls_show(struct uvcg_uncompressed *unc, char *page)
+uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
 {
+       struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
        return uvcg_format_bma_controls_show(&unc->fmt, page);
 }
 
 static inline ssize_t
-uvcg_uncompressed_bma_controls_store(struct uvcg_uncompressed *ch,
+uvcg_uncompressed_bma_controls_store(struct config_item *item,
                                     const char *page, size_t len)
 {
-       return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+       struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
+       return uvcg_format_bma_controls_store(&unc->fmt, page, len);
 }
 
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_bma_controls =
-       __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
-                       uvcg_uncompressed_bma_controls_show,
-                       uvcg_uncompressed_bma_controls_store);
+UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
-       &uvcg_uncompressed_guid_format.attr,
-       &uvcg_uncompressed_b_bits_per_pixel.attr,
-       &uvcg_uncompressed_b_default_frame_index.attr,
-       &uvcg_uncompressed_b_aspect_ratio_x.attr,
-       &uvcg_uncompressed_b_aspect_ratio_y.attr,
-       &uvcg_uncompressed_bm_interface_flags.attr,
-       &uvcg_uncompressed_bma_controls.attr,
+       &uvcg_uncompressed_attr_guid_format,
+       &uvcg_uncompressed_attr_b_bits_per_pixel,
+       &uvcg_uncompressed_attr_b_default_frame_index,
+       &uvcg_uncompressed_attr_b_aspect_ratio_x,
+       &uvcg_uncompressed_attr_b_aspect_ratio_y,
+       &uvcg_uncompressed_attr_bm_interface_flags,
+       &uvcg_uncompressed_attr_bma_controls,
        NULL,
 };
 
 static struct config_item_type uvcg_uncompressed_type = {
-       .ct_item_ops    = &uvcg_uncompressed_item_ops,
        .ct_group_ops   = &uvcg_uncompressed_group_ops,
        .ct_attrs       = uvcg_uncompressed_attrs,
        .ct_owner       = THIS_MODULE,
@@ -1605,22 +1532,15 @@ static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
                struct uvcg_mjpeg, fmt);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_mjpeg);
-CONFIGFS_ATTR_OPS(uvcg_mjpeg);
-
-static struct configfs_item_operations uvcg_mjpeg_item_ops = {
-       .show_attribute         = uvcg_mjpeg_attr_show,
-       .store_attribute        = uvcg_mjpeg_attr_store,
-};
-
 static struct configfs_group_operations uvcg_mjpeg_group_ops = {
        .make_item              = uvcg_frame_make,
        .drop_item              = uvcg_frame_drop,
 };
 
 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv)                         \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
 {                                                                      \
+       struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);                     \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1639,13 +1559,12 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_mjpeg_attribute                                     \
-       uvcg_mjpeg_##cname =                                            \
-       __CONFIGFS_ATTR_RO(aname, uvcg_mjpeg_##cname##_show)
+UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
 
 #define UVCG_MJPEG_ATTR(cname, aname, conv)                            \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
 {                                                                      \
+       struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);                     \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1665,9 +1584,10 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
 }                                                                      \
                                                                        \
 static ssize_t                                                         \
-uvcg_mjpeg_##cname##_store(struct uvcg_mjpeg *u,                       \
+uvcg_mjpeg_##cname##_store(struct config_item *item,                   \
                           const char *page, size_t len)                \
 {                                                                      \
+       struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);                     \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;     \
@@ -1701,11 +1621,7 @@ end:                                                                     \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct uvcg_mjpeg_attribute                                     \
-       uvcg_mjpeg_##cname =                                            \
-       __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR,                       \
-                       uvcg_mjpeg_##cname##_show,                      \
-                       uvcg_mjpeg_##cname##_store)
+UVC_ATTR(uvcg_mjpeg_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -1722,35 +1638,33 @@ UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
 #undef UVCG_MJPEG_ATTR_RO
 
 static inline ssize_t
-uvcg_mjpeg_bma_controls_show(struct uvcg_mjpeg *unc, char *page)
+uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
 {
-       return uvcg_format_bma_controls_show(&unc->fmt, page);
+       struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+       return uvcg_format_bma_controls_show(&u->fmt, page);
 }
 
 static inline ssize_t
-uvcg_mjpeg_bma_controls_store(struct uvcg_mjpeg *ch,
+uvcg_mjpeg_bma_controls_store(struct config_item *item,
                                     const char *page, size_t len)
 {
-       return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+       struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+       return uvcg_format_bma_controls_store(&u->fmt, page, len);
 }
 
-static struct uvcg_mjpeg_attribute uvcg_mjpeg_bma_controls =
-       __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
-                       uvcg_mjpeg_bma_controls_show,
-                       uvcg_mjpeg_bma_controls_store);
+UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
 
 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
-       &uvcg_mjpeg_b_default_frame_index.attr,
-       &uvcg_mjpeg_bm_flags.attr,
-       &uvcg_mjpeg_b_aspect_ratio_x.attr,
-       &uvcg_mjpeg_b_aspect_ratio_y.attr,
-       &uvcg_mjpeg_bm_interface_flags.attr,
-       &uvcg_mjpeg_bma_controls.attr,
+       &uvcg_mjpeg_attr_b_default_frame_index,
+       &uvcg_mjpeg_attr_bm_flags,
+       &uvcg_mjpeg_attr_b_aspect_ratio_x,
+       &uvcg_mjpeg_attr_b_aspect_ratio_y,
+       &uvcg_mjpeg_attr_bm_interface_flags,
+       &uvcg_mjpeg_attr_bma_controls,
        NULL,
 };
 
 static struct config_item_type uvcg_mjpeg_type = {
-       .ct_item_ops    = &uvcg_mjpeg_item_ops,
        .ct_group_ops   = &uvcg_mjpeg_group_ops,
        .ct_attrs       = uvcg_mjpeg_attrs,
        .ct_owner       = THIS_MODULE,
@@ -1811,17 +1725,12 @@ static inline struct uvcg_default_color_matching
                            struct uvcg_default_color_matching, group);
 }
 
-CONFIGFS_ATTR_STRUCT(uvcg_default_color_matching);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_color_matching);
-
-static struct configfs_item_operations uvcg_default_color_matching_item_ops = {
-       .show_attribute         = uvcg_default_color_matching_attr_show,
-};
-
 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv)           \
 static ssize_t uvcg_default_color_matching_##cname##_show(             \
-       struct uvcg_default_color_matching *dc, char *page)             \
+       struct config_item *item, char *page)           \
 {                                                                      \
+       struct uvcg_default_color_matching *dc =                        \
+               to_uvcg_default_color_matching(item);                   \
        struct f_uvc_opts *opts;                                        \
        struct config_item *opts_item;                                  \
        struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;        \
@@ -1842,9 +1751,7 @@ static ssize_t uvcg_default_color_matching_##cname##_show(                \
        return result;                                                  \
 }                                                                      \
                                                                        \
-static struct uvcg_default_color_matching_attribute                    \
-       uvcg_default_color_matching_##cname =                           \
-       __CONFIGFS_ATTR_RO(aname, uvcg_default_color_matching_##cname##_show)
+UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -1860,14 +1767,13 @@ UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
 
 static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
-       &uvcg_default_color_matching_b_color_primaries.attr,
-       &uvcg_default_color_matching_b_transfer_characteristics.attr,
-       &uvcg_default_color_matching_b_matrix_coefficients.attr,
+       &uvcg_default_color_matching_attr_b_color_primaries,
+       &uvcg_default_color_matching_attr_b_transfer_characteristics,
+       &uvcg_default_color_matching_attr_b_matrix_coefficients,
        NULL,
 };
 
 static struct config_item_type uvcg_default_color_matching_type = {
-       .ct_item_ops    = &uvcg_default_color_matching_item_ops,
        .ct_attrs       = uvcg_default_color_matching_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -2285,9 +2191,6 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
                            func_inst.group);
 }
 
-CONFIGFS_ATTR_STRUCT(f_uvc_opts);
-CONFIGFS_ATTR_OPS(f_uvc_opts);
-
 static void uvc_attr_release(struct config_item *item)
 {
        struct f_uvc_opts *opts = to_f_uvc_opts(item);
@@ -2297,14 +2200,13 @@ static void uvc_attr_release(struct config_item *item)
 
 static struct configfs_item_operations uvc_item_ops = {
        .release                = uvc_attr_release,
-       .show_attribute         = f_uvc_opts_attr_show,
-       .store_attribute        = f_uvc_opts_attr_store,
 };
 
 #define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit)           \
 static ssize_t f_uvc_opts_##cname##_show(                              \
-       struct f_uvc_opts *opts, char *page)                            \
+       struct config_item *item, char *page)                           \
 {                                                                      \
+       struct f_uvc_opts *opts = to_f_uvc_opts(item);                  \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
@@ -2315,9 +2217,10 @@ static ssize_t f_uvc_opts_##cname##_show(                                \
 }                                                                      \
                                                                        \
 static ssize_t                                                         \
-f_uvc_opts_##cname##_store(struct f_uvc_opts *opts,                    \
+f_uvc_opts_##cname##_store(struct config_item *item,                   \
                           const char *page, size_t len)                \
 {                                                                      \
+       struct f_uvc_opts *opts = to_f_uvc_opts(item);                  \
        int ret;                                                        \
        uxx num;                                                        \
                                                                        \
@@ -2342,11 +2245,7 @@ end:                                                                     \
        return ret;                                                     \
 }                                                                      \
                                                                        \
-static struct f_uvc_opts_attribute                                     \
-       f_uvc_opts_attribute_##cname =                                  \
-       __CONFIGFS_ATTR(cname, S_IRUGO | S_IWUSR,                       \
-                       f_uvc_opts_##cname##_show,                      \
-                       f_uvc_opts_##cname##_store)
+UVC_ATTR(f_uvc_opts_, cname, aname)
 
 #define identity_conv(x) (x)
 
@@ -2362,9 +2261,9 @@ UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
 #undef UVCG_OPTS_ATTR
 
 static struct configfs_attribute *uvc_attrs[] = {
-       &f_uvc_opts_attribute_streaming_interval.attr,
-       &f_uvc_opts_attribute_streaming_maxpacket.attr,
-       &f_uvc_opts_attribute_streaming_maxburst.attr,
+       &f_uvc_opts_attr_streaming_interval,
+       &f_uvc_opts_attr_streaming_maxpacket,
+       &f_uvc_opts_attr_streaming_maxburst,
        NULL,
 };
 
index 778e42abb3cb8703fcf19b829e21f764ac798d1e..22e56158d5850236242375d036f70250b676dac7 100644 (file)
@@ -19,8 +19,6 @@
 #include <scsi/scsi_tcq.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 #include <asm/unaligned.h>
 
 #include "tcm_usb_gadget.h"
@@ -1467,23 +1465,21 @@ static void usbg_drop_tport(struct se_wwn *wwn)
 /*
  * If somebody feels like dropping the version property, go ahead.
  */
-static ssize_t usbg_wwn_show_attr_version(
-       struct target_fabric_configfs *tf,
-       char *page)
+static ssize_t usbg_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "usb-gadget fabric module\n");
 }
-TF_WWN_ATTR_RO(usbg, version);
+
+CONFIGFS_ATTR_RO(usbg_wwn_, version);
 
 static struct configfs_attribute *usbg_wwn_attrs[] = {
-       &usbg_wwn_version.attr,
+       &usbg_wwn_attr_version,
        NULL,
 };
 
-static ssize_t tcm_usbg_tpg_show_enable(
-               struct se_portal_group *se_tpg,
-               char *page)
+static ssize_t tcm_usbg_tpg_enable_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct usbg_tpg  *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
 
        return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
@@ -1492,11 +1488,10 @@ static ssize_t tcm_usbg_tpg_show_enable(
 static int usbg_attach(struct usbg_tpg *);
 static void usbg_detach(struct usbg_tpg *);
 
-static ssize_t tcm_usbg_tpg_store_enable(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t tcm_usbg_tpg_enable_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct usbg_tpg  *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
        unsigned long op;
        ssize_t ret;
@@ -1523,12 +1518,10 @@ static ssize_t tcm_usbg_tpg_store_enable(
 out:
        return count;
 }
-TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
 
-static ssize_t tcm_usbg_tpg_show_nexus(
-               struct se_portal_group *se_tpg,
-               char *page)
+static ssize_t tcm_usbg_tpg_nexus_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
        struct tcm_usbg_nexus *tv_nexus;
        ssize_t ret;
@@ -1636,11 +1629,10 @@ static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
        return ret;
 }
 
-static ssize_t tcm_usbg_tpg_store_nexus(
-               struct se_portal_group *se_tpg,
-               const char *page,
-               size_t count)
+static ssize_t tcm_usbg_tpg_nexus_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
        unsigned char i_port[USBG_NAMELEN], *ptr;
        int ret;
@@ -1670,11 +1662,13 @@ static ssize_t tcm_usbg_tpg_store_nexus(
                return ret;
        return count;
 }
-TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR(tcm_usbg_tpg_, enable);
+CONFIGFS_ATTR(tcm_usbg_tpg_, nexus);
 
 static struct configfs_attribute *usbg_base_attrs[] = {
-       &tcm_usbg_tpg_enable.attr,
-       &tcm_usbg_tpg_nexus.attr,
+       &tcm_usbg_tpg_attr_enable,
+       &tcm_usbg_tpg_attr_nexus,
        NULL,
 };
 
index f0f2b066ac08366d353b046d3a3a193600977d1d..f92f5aff0dd5e8ece600cc44b5ba6168e3f1bb81 100644 (file)
@@ -1633,7 +1633,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
        spin_lock(&udc->lock);
 
        int_enb = usba_int_enb_get(udc);
-       status = usba_readl(udc, INT_STA) & int_enb;
+       status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
        DBG(DBG_INT, "irq, status=%#08x\n", status);
 
        if (status & USBA_DET_SUSPEND) {
index 5d2d7e954bd4cb8dbaa51ec1121e236e8f472dce..0230965fb78cf3433702932625aee270dbf90535 100644 (file)
@@ -782,12 +782,15 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        status |= USB_PORT_STAT_SUSPEND;
                }
        }
-       if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0
-                       && (raw_port_status & PORT_POWER)
-                       && (bus_state->suspended_ports & (1 << wIndex))) {
-               bus_state->suspended_ports &= ~(1 << wIndex);
-               if (hcd->speed < HCD_USB3)
-                       bus_state->port_c_suspend |= 1 << wIndex;
+       if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
+           (raw_port_status & PORT_POWER)) {
+               if (bus_state->suspended_ports & (1 << wIndex)) {
+                       bus_state->suspended_ports &= ~(1 << wIndex);
+                       if (hcd->speed < HCD_USB3)
+                               bus_state->port_c_suspend |= 1 << wIndex;
+               }
+               bus_state->resume_done[wIndex] = 0;
+               clear_bit(wIndex, &bus_state->resuming_ports);
        }
        if (raw_port_status & PORT_CONNECT) {
                status |= USB_PORT_STAT_CONNECTION;
index fa836251ca21e4f19c59b3fd37b3b788b7b81008..6c5e8133cf87c4b203e2072de5b7275c4d944365 100644 (file)
@@ -3896,28 +3896,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        return ret;
 }
 
-static int ep_ring_is_processing(struct xhci_hcd *xhci,
-               int slot_id, unsigned int ep_index)
-{
-       struct xhci_virt_device *xdev;
-       struct xhci_ring *ep_ring;
-       struct xhci_ep_ctx *ep_ctx;
-       struct xhci_virt_ep *xep;
-       dma_addr_t hw_deq;
-
-       xdev = xhci->devs[slot_id];
-       xep = &xhci->devs[slot_id]->eps[ep_index];
-       ep_ring = xep->ring;
-       ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
-
-       if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
-               return 0;
-
-       hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
-       return (hw_deq !=
-               xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
-}
-
 /*
  * Check transfer ring to guarantee there is enough room for the urb.
  * Update ISO URB start_frame and interval.
@@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
        }
 
        /* Calculate the start frame and put it in urb->start_frame. */
-       if (HCC_CFC(xhci->hcc_params) &&
-                       ep_ring_is_processing(xhci, slot_id, ep_index)) {
-               urb->start_frame = xep->next_frame_id;
-               goto skip_start_over;
+       if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) {
+               if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
+                               EP_STATE_RUNNING) {
+                       urb->start_frame = xep->next_frame_id;
+                       goto skip_start_over;
+               }
        }
 
        start_frame = readl(&xhci->run_regs->microframe_index);
index 6e7dc6f93978c54e300caaa1b53155a672c91019..dfa44d3e8eee469c9b8321fed57056ebe5813a2a 100644 (file)
@@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci)
        command |= CMD_RESET;
        writel(command, &xhci->op_regs->command);
 
+       /* Existing Intel xHCI controllers require a delay of 1 mS,
+        * after setting the CMD_RESET bit, and before accessing any
+        * HC registers. This allows the HC to complete the
+        * reset operation and be ready for HC register access.
+        * Without this delay, the subsequent HC register access,
+        * may result in a system hang very rarely.
+        */
+       if (xhci->quirks & XHCI_INTEL_HOST)
+               udelay(1000);
+
        ret = xhci_handshake(&xhci->op_regs->command,
                        CMD_RESET, 0, 10 * 1000 * 1000);
        if (ret)
index ba13529cbd52ff82658e88bdba30db82a8e99790..18cfc0a361cb340612bdf943d79a6302694afc43 100644 (file)
@@ -132,7 +132,7 @@ static inline struct musb *dev_to_musb(struct device *dev)
 /*-------------------------------------------------------------------------*/
 
 #ifndef CONFIG_BLACKFIN
-static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
+static int musb_ulpi_read(struct usb_phy *phy, u32 reg)
 {
        void __iomem *addr = phy->io_priv;
        int     i = 0;
@@ -151,7 +151,7 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
         * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
         */
 
-       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
                        MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
 
@@ -176,7 +176,7 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
        return ret;
 }
 
-static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
+static int musb_ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
 {
        void __iomem *addr = phy->io_priv;
        int     i = 0;
@@ -191,8 +191,8 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
        power &= ~MUSB_POWER_SUSPENDM;
        musb_writeb(addr, MUSB_POWER, power);
 
-       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
-       musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
+       musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)val);
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
 
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
@@ -1668,7 +1668,7 @@ EXPORT_SYMBOL_GPL(musb_interrupt);
 static bool use_dma = 1;
 
 /* "modprobe ... use_dma=0" etc */
-module_param(use_dma, bool, 0);
+module_param(use_dma, bool, 0644);
 MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
 
 void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
index 26c65e66cc0f1db8680933d13ed2d2b960603906..795a45b1b25bacb016552b4d0635166965ebfce6 100644 (file)
@@ -112,22 +112,32 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
        struct musb     *musb = ep->musb;
        void __iomem    *epio = ep->regs;
        u16             csr;
-       u16             lastcsr = 0;
        int             retries = 1000;
 
        csr = musb_readw(epio, MUSB_TXCSR);
        while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
-               if (csr != lastcsr)
-                       dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
-               lastcsr = csr;
                csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
                musb_writew(epio, MUSB_TXCSR, csr);
                csr = musb_readw(epio, MUSB_TXCSR);
-               if (WARN(retries-- < 1,
+
+               /*
+                * FIXME: sometimes the tx fifo flush failed, it has been
+                * observed during device disconnect on AM335x.
+                *
+                * To reproduce the issue, ensure tx urb(s) are queued when
+                * unplug the usb device which is connected to AM335x usb
+                * host port.
+                *
+                * I found using a usb-ethernet device and running iperf
+                * (client on AM335x) has very high chance to trigger it.
+                *
+                * Better to turn on dev_dbg() in musb_cleanup_urb() with
+                * CPPI enabled to see the issue when aborting the tx channel.
+                */
+               if (dev_WARN_ONCE(musb->controller, retries-- < 1,
                                "Could not flush host TX%d fifo: csr: %04x\n",
                                ep->epnum, csr))
                        return;
-               mdelay(1);
        }
 }
 
index 173132416170108b6a156568f53f3c51224a86c2..22e8ecb6bfbd282236a77525cf4cabda25555c66 100644 (file)
@@ -21,7 +21,6 @@ config AB8500_USB
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
        depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
-       select USB_OTG
        select USB_PHY
        help
          Enable this to support Freescale USB OTG transceiver.
@@ -168,8 +167,7 @@ config USB_QCOM_8X16_PHY
 
 config USB_MV_OTG
        tristate "Marvell USB OTG support"
-       depends on USB_EHCI_MV && USB_MV_UDC && PM
-       select USB_OTG
+       depends on USB_EHCI_MV && USB_MV_UDC && PM && USB_OTG
        select USB_PHY
        help
          Say Y here if you want to build Marvell USB OTG transciever
index 4d863ebc117c0f59cce46f39fda4d191e93b9843..b7536af777ab9c4f083d7b88ff2bfe093fca9e21 100644 (file)
@@ -452,10 +452,13 @@ static int mxs_phy_probe(struct platform_device *pdev)
        struct clk *clk;
        struct mxs_phy *mxs_phy;
        int ret;
-       const struct of_device_id *of_id =
-                       of_match_device(mxs_phy_dt_ids, &pdev->dev);
+       const struct of_device_id *of_id;
        struct device_node *np = pdev->dev.of_node;
 
+       of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
index 1270906ccb95808714d174f0461a081c8d1d1cc6..c4bf2de6d14ec3a47259f06977e27ea1f3329ed1 100644 (file)
@@ -105,7 +105,6 @@ static int omap_otg_probe(struct platform_device *pdev)
        extcon = extcon_get_extcon_dev(config->extcon);
        if (!extcon)
                return -EPROBE_DEFER;
-       otg_dev->extcon = extcon;
 
        otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
        if (!otg_dev)
@@ -115,6 +114,7 @@ static int omap_otg_probe(struct platform_device *pdev)
        if (IS_ERR(otg_dev->base))
                return PTR_ERR(otg_dev->base);
 
+       otg_dev->extcon = extcon;
        otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
        otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
 
index 685fef71d3d14e28ce125983b3508ae73ed6579c..f2280606b73c0c897d83d7738747b3d6f97a2c71 100644 (file)
@@ -161,6 +161,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
 #define NOVATELWIRELESS_PRODUCT_E362           0x9010
 #define NOVATELWIRELESS_PRODUCT_E371           0x9011
+#define NOVATELWIRELESS_PRODUCT_U620L          0x9022
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
 #define NOVATELWIRELESS_PRODUCT_MC551          0xB001
 
@@ -354,6 +355,7 @@ static void option_instat_callback(struct urb *urb);
 /* This is the 4G XS Stick W14 a.k.a. Mobilcom Debitel Surf-Stick *
  * It seems to contain a Qualcomm QSC6240/6290 chipset            */
 #define FOUR_G_SYSTEMS_PRODUCT_W14             0x9603
+#define FOUR_G_SYSTEMS_PRODUCT_W100            0x9b01
 
 /* iBall 3.5G connect wireless modem */
 #define IBALL_3_5G_CONNECT                     0x9605
@@ -519,6 +521,11 @@ static const struct option_blacklist_info four_g_w14_blacklist = {
        .sendsetup = BIT(0) | BIT(1),
 };
 
+static const struct option_blacklist_info four_g_w100_blacklist = {
+       .sendsetup = BIT(1) | BIT(2),
+       .reserved = BIT(3),
+};
+
 static const struct option_blacklist_info alcatel_x200_blacklist = {
        .sendsetup = BIT(0) | BIT(1),
        .reserved = BIT(4),
@@ -1052,6 +1059,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U620L, 0xff, 0x00, 0x00) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -1641,6 +1649,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
          .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
        },
+       { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W100),
+         .driver_info = (kernel_ulong_t)&four_g_w100_blacklist
+       },
        { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
index 5022fcfa02605a604f6998ef7dcbf0d3f0b2b590..9919d2a9faf278177aacf32c149fda22b00a1d83 100644 (file)
@@ -22,6 +22,8 @@
 #define DRIVER_AUTHOR "Qualcomm Inc"
 #define DRIVER_DESC "Qualcomm USB Serial driver"
 
+#define QUECTEL_EC20_PID       0x9215
+
 /* standard device layouts supported by this driver */
 enum qcserial_layouts {
        QCSERIAL_G2K = 0,       /* Gobi 2000 */
@@ -171,6 +173,38 @@ static const struct usb_device_id id_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
+static int handle_quectel_ec20(struct device *dev, int ifnum)
+{
+       int altsetting = 0;
+
+       /*
+        * Quectel EC20 Mini PCIe LTE module layout:
+        * 0: DM/DIAG (use libqcdm from ModemManager for communication)
+        * 1: NMEA
+        * 2: AT-capable modem port
+        * 3: Modem interface
+        * 4: NDIS
+        */
+       switch (ifnum) {
+       case 0:
+               dev_dbg(dev, "Quectel EC20 DM/DIAG interface found\n");
+               break;
+       case 1:
+               dev_dbg(dev, "Quectel EC20 NMEA GPS interface found\n");
+               break;
+       case 2:
+       case 3:
+               dev_dbg(dev, "Quectel EC20 Modem port found\n");
+               break;
+       case 4:
+               /* Don't claim the QMI/net interface */
+               altsetting = -1;
+               break;
+       }
+
+       return altsetting;
+}
+
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
        struct usb_host_interface *intf = serial->interface->cur_altsetting;
@@ -181,6 +215,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        int altsetting = -1;
        bool sendsetup = false;
 
+       /* we only support vendor specific functions */
+       if (intf->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+               goto done;
+
        nintf = serial->dev->actconfig->desc.bNumInterfaces;
        dev_dbg(dev, "Num Interfaces = %d\n", nintf);
        ifnum = intf->desc.bInterfaceNumber;
@@ -240,6 +278,12 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                        altsetting = -1;
                break;
        case QCSERIAL_G2K:
+               /* handle non-standard layouts */
+               if (nintf == 5 && id->idProduct == QUECTEL_EC20_PID) {
+                       altsetting = handle_quectel_ec20(dev, ifnum);
+                       goto done;
+               }
+
                /*
                 * Gobi 2K+ USB layout:
                 * 0: QMI/net
@@ -301,29 +345,39 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                break;
        case QCSERIAL_HWI:
                /*
-                * Huawei layout:
-                * 0: AT-capable modem port
-                * 1: DM/DIAG
-                * 2: AT-capable modem port
-                * 3: CCID-compatible PCSC interface
-                * 4: QMI/net
-                * 5: NMEA
+                * Huawei devices map functions by subclass + protocol
+                * instead of interface numbers. The protocol identify
+                * a specific function, while the subclass indicate a
+                * specific firmware source
+                *
+                * This is a blacklist of functions known to be
+                * non-serial.  The rest are assumed to be serial and
+                * will be handled by this driver
                 */
-               switch (ifnum) {
-               case 0:
-               case 2:
-                       dev_dbg(dev, "Modem port found\n");
-                       break;
-               case 1:
-                       dev_dbg(dev, "DM/DIAG interface found\n");
-                       break;
-               case 5:
-                       dev_dbg(dev, "NMEA GPS interface found\n");
-                       break;
-               default:
-                       /* don't claim any unsupported interface */
+               switch (intf->desc.bInterfaceProtocol) {
+                       /* QMI combined (qmi_wwan) */
+               case 0x07:
+               case 0x37:
+               case 0x67:
+                       /* QMI data (qmi_wwan) */
+               case 0x08:
+               case 0x38:
+               case 0x68:
+                       /* QMI control (qmi_wwan) */
+               case 0x09:
+               case 0x39:
+               case 0x69:
+                       /* NCM like (huawei_cdc_ncm) */
+               case 0x16:
+               case 0x46:
+               case 0x76:
                        altsetting = -1;
                        break;
+               default:
+                       dev_dbg(dev, "Huawei type serial port found (%02x/%02x/%02x)\n",
+                               intf->desc.bInterfaceClass,
+                               intf->desc.bInterfaceSubClass,
+                               intf->desc.bInterfaceProtocol);
                }
                break;
        default:
index e9da41d9fe7fce04c24ee604b3d17a832dbded0e..2694df2f4559b0116e5e96ebc0587017f818fc39 100644 (file)
@@ -159,6 +159,7 @@ static const struct usb_device_id ti_id_table_3410[] = {
        { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) },
        { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+       { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) },
        { }     /* terminator */
 };
 
@@ -191,6 +192,7 @@ static const struct usb_device_id ti_id_table_combined[] = {
        { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
        { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
+       { USB_DEVICE(HONEYWELL_VENDOR_ID, HONEYWELL_HGI80_PRODUCT_ID) },
        { }     /* terminator */
 };
 
index 4a2423e84d55820b594ca43ed99fc8ae88b2f002..98f35c656c02d8589828e54a79b4675b76c35a2e 100644 (file)
 #define ABBOTT_PRODUCT_ID              ABBOTT_STEREO_PLUG_ID
 #define ABBOTT_STRIP_PORT_ID           0x3420
 
+/* Honeywell vendor and product IDs */
+#define HONEYWELL_VENDOR_ID            0x10ac
+#define HONEYWELL_HGI80_PRODUCT_ID     0x0102  /* Honeywell HGI80 */
+
 /* Commands */
 #define TI_GET_VERSION                 0x01
 #define TI_GET_PORT_STATUS             0x02
index 48ca9c204354168f079a1e9e5ceaf2ac4b74a0f5..e6915166443607283f8229eaca83fac38ed68377 100644 (file)
@@ -812,7 +812,6 @@ static struct scsi_host_template uas_host_template = {
        .this_id = -1,
        .sg_tablesize = SG_NONE,
        .skip_settle_delay = 1,
-       .use_blk_tags = 1,
 };
 
 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
@@ -929,10 +928,6 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (result)
                goto set_alt0;
 
-       result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
-       if (result)
-               goto free_streams;
-
        usb_set_intfdata(intf, shost);
        result = scsi_add_host(shost, &intf->dev);
        if (result)
index 850d86ca685b273344271eda7c95ad4f82b28244..da6e2ce77495b21ec127209664567b7e2f8f467e 100644 (file)
@@ -31,6 +31,21 @@ menuconfig VFIO
 
          If you don't know what to do here, say N.
 
+menuconfig VFIO_NOIOMMU
+       bool "VFIO No-IOMMU support"
+       depends on VFIO
+       help
+         VFIO is built on the ability to isolate devices using the IOMMU.
+         Only with an IOMMU can userspace access to DMA capable devices be
+         considered secure.  VFIO No-IOMMU mode enables IOMMU groups for
+         devices without IOMMU backing for the purpose of re-using the VFIO
+         infrastructure in a non-secure mode.  Use of this mode will result
+         in an unsupportable kernel and will therefore taint the kernel.
+         Device assignment to virtual machines is also not possible with
+         this mode since there is no IOMMU to provide DMA translation.
+
+         If you don't know what to do here, say N.
+
 source "drivers/vfio/pci/Kconfig"
 source "drivers/vfio/platform/Kconfig"
 source "virt/lib/Kconfig"
index 964ad572aaeede1fc7d2522a9fdb69b7d66f3faa..32b88bd2c82c7e3a3f4cd8cae11a253a171c76fa 100644 (file)
@@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
                return -EINVAL;
 
-       group = iommu_group_get(&pdev->dev);
+       group = vfio_iommu_group_get(&pdev->dev);
        if (!group)
                return -EINVAL;
 
        vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
        if (!vdev) {
-               iommu_group_put(group);
+               vfio_iommu_group_put(group, &pdev->dev);
                return -ENOMEM;
        }
 
@@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
        if (ret) {
-               iommu_group_put(group);
+               vfio_iommu_group_put(group, &pdev->dev);
                kfree(vdev);
                return ret;
        }
@@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
        if (!vdev)
                return;
 
-       iommu_group_put(pdev->dev.iommu_group);
+       vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
        kfree(vdev);
 
        if (vfio_pci_is_vga(pdev)) {
index ff75ca31a199d1a2c468b71bf0d9b4566f1894b7..fe2b470d7ec6b33c8fd75ffbfccb1168a6975ca2 100644 (file)
@@ -46,7 +46,7 @@
  *   0: Removed from the user visible capability list
  *   FF: Variable length
  */
-static u8 pci_cap_length[] = {
+static const u8 pci_cap_length[PCI_CAP_ID_MAX + 1] = {
        [PCI_CAP_ID_BASIC]      = PCI_STD_HEADER_SIZEOF, /* pci config header */
        [PCI_CAP_ID_PM]         = PCI_PM_SIZEOF,
        [PCI_CAP_ID_AGP]        = PCI_AGP_SIZEOF,
@@ -74,7 +74,7 @@ static u8 pci_cap_length[] = {
  *   0: Removed or masked from the user visible capabilty list
  *   FF: Variable length
  */
-static u16 pci_ext_cap_length[] = {
+static const u16 pci_ext_cap_length[PCI_EXT_CAP_ID_MAX + 1] = {
        [PCI_EXT_CAP_ID_ERR]    =       PCI_ERR_ROOT_COMMAND,
        [PCI_EXT_CAP_ID_VC]     =       0xFF,
        [PCI_EXT_CAP_ID_DSN]    =       PCI_EXT_CAP_DSN_SIZEOF,
@@ -671,6 +671,73 @@ static int __init init_pci_cap_pm_perm(struct perm_bits *perm)
        return 0;
 }
 
+static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
+                                int count, struct perm_bits *perm,
+                                int offset, __le32 val)
+{
+       struct pci_dev *pdev = vdev->pdev;
+       __le16 *paddr = (__le16 *)(vdev->vconfig + pos - offset + PCI_VPD_ADDR);
+       __le32 *pdata = (__le32 *)(vdev->vconfig + pos - offset + PCI_VPD_DATA);
+       u16 addr;
+       u32 data;
+
+       /*
+        * Write through to emulation.  If the write includes the upper byte
+        * of PCI_VPD_ADDR, then the PCI_VPD_ADDR_F bit is written and we
+        * have work to do.
+        */
+       count = vfio_default_config_write(vdev, pos, count, perm, offset, val);
+       if (count < 0 || offset > PCI_VPD_ADDR + 1 ||
+           offset + count <= PCI_VPD_ADDR + 1)
+               return count;
+
+       addr = le16_to_cpu(*paddr);
+
+       if (addr & PCI_VPD_ADDR_F) {
+               data = le32_to_cpu(*pdata);
+               if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4)
+                       return count;
+       } else {
+               if (pci_read_vpd(pdev, addr, 4, &data) != 4)
+                       return count;
+               *pdata = cpu_to_le32(data);
+       }
+
+       /*
+        * Toggle PCI_VPD_ADDR_F in the emulated PCI_VPD_ADDR register to
+        * signal completion.  If an error occurs above, we assume that not
+        * toggling this bit will induce a driver timeout.
+        */
+       addr ^= PCI_VPD_ADDR_F;
+       *paddr = cpu_to_le16(addr);
+
+       return count;
+}
+
+/* Permissions for Vital Product Data capability */
+static int __init init_pci_cap_vpd_perm(struct perm_bits *perm)
+{
+       if (alloc_perm_bits(perm, pci_cap_length[PCI_CAP_ID_VPD]))
+               return -ENOMEM;
+
+       perm->writefn = vfio_vpd_config_write;
+
+       /*
+        * We always virtualize the next field so we can remove
+        * capabilities from the chain if we want to.
+        */
+       p_setb(perm, PCI_CAP_LIST_NEXT, (u8)ALL_VIRT, NO_WRITE);
+
+       /*
+        * Both the address and data registers are virtualized to
+        * enable access through the pci_vpd_read/write functions
+        */
+       p_setw(perm, PCI_VPD_ADDR, (u16)ALL_VIRT, (u16)ALL_WRITE);
+       p_setd(perm, PCI_VPD_DATA, ALL_VIRT, ALL_WRITE);
+
+       return 0;
+}
+
 /* Permissions for PCI-X capability */
 static int __init init_pci_cap_pcix_perm(struct perm_bits *perm)
 {
@@ -790,6 +857,7 @@ void vfio_pci_uninit_perm_bits(void)
        free_perm_bits(&cap_perms[PCI_CAP_ID_BASIC]);
 
        free_perm_bits(&cap_perms[PCI_CAP_ID_PM]);
+       free_perm_bits(&cap_perms[PCI_CAP_ID_VPD]);
        free_perm_bits(&cap_perms[PCI_CAP_ID_PCIX]);
        free_perm_bits(&cap_perms[PCI_CAP_ID_EXP]);
        free_perm_bits(&cap_perms[PCI_CAP_ID_AF]);
@@ -807,7 +875,7 @@ int __init vfio_pci_init_perm_bits(void)
 
        /* Capabilities */
        ret |= init_pci_cap_pm_perm(&cap_perms[PCI_CAP_ID_PM]);
-       cap_perms[PCI_CAP_ID_VPD].writefn = vfio_raw_config_write;
+       ret |= init_pci_cap_vpd_perm(&cap_perms[PCI_CAP_ID_VPD]);
        ret |= init_pci_cap_pcix_perm(&cap_perms[PCI_CAP_ID_PCIX]);
        cap_perms[PCI_CAP_ID_VNDR].writefn = vfio_raw_config_write;
        ret |= init_pci_cap_exp_perm(&cap_perms[PCI_CAP_ID_EXP]);
index 9ce8afe2845041cbd064113bba85309678e37d7a..41a6224f5e6b6ab1b962605ac4e9aede6cac66f7 100644 (file)
@@ -1,10 +1,12 @@
-
-vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-base-y := vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-y := vfio_platform.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform-base.o
 obj-$(CONFIG_VFIO_PLATFORM) += reset/
 
 vfio-amba-y := vfio_amba.o
 
 obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
+obj-$(CONFIG_VFIO_AMBA) += vfio-platform-base.o
 obj-$(CONFIG_VFIO_AMBA) += reset/
index 746b96b0003be87f06af9037bafcf93c303c50aa..70cccc582bee6ec86047e38b473dc1be8acc10ff 100644 (file)
@@ -5,3 +5,11 @@ config VFIO_PLATFORM_CALXEDAXGMAC_RESET
          Enables the VFIO platform driver to handle reset for Calxeda xgmac
 
          If you don't know what to do here, say N.
+
+config VFIO_PLATFORM_AMDXGBE_RESET
+       tristate "VFIO support for AMD XGBE reset"
+       depends on VFIO_PLATFORM
+       help
+         Enables the VFIO platform driver to handle reset for AMD XGBE
+
+         If you don't know what to do here, say N.
index 2a486af9f8fa5da0a78f3ee000f8740553b2958a..93f4e232697bd62a9761fae12ad479e29eee88be 100644 (file)
@@ -1,5 +1,7 @@
 vfio-platform-calxedaxgmac-y := vfio_platform_calxedaxgmac.o
+vfio-platform-amdxgbe-y := vfio_platform_amdxgbe.o
 
 ccflags-y += -Idrivers/vfio/platform
 
 obj-$(CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET) += vfio-platform-calxedaxgmac.o
+obj-$(CONFIG_VFIO_PLATFORM_AMDXGBE_RESET) += vfio-platform-amdxgbe.o
diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c
new file mode 100644 (file)
index 0000000..da5356f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * VFIO platform driver specialized for AMD xgbe reset
+ * reset code is inherited from AMD xgbe native driver
+ *
+ * Copyright (c) 2015 Linaro Ltd.
+ *              www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <uapi/linux/mdio.h>
+#include <linux/delay.h>
+
+#include "vfio_platform_private.h"
+
+#define DMA_MR                 0x3000
+#define MAC_VR                 0x0110
+#define DMA_ISR                        0x3008
+#define MAC_ISR                        0x00b0
+#define PCS_MMD_SELECT         0xff
+#define MDIO_AN_INT            0x8002
+#define MDIO_AN_INTMASK                0x8001
+
+static unsigned int xmdio_read(void *ioaddr, unsigned int mmd,
+                              unsigned int reg)
+{
+       unsigned int mmd_address, value;
+
+       mmd_address = (mmd << 16) | ((reg) & 0xffff);
+       iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
+       value = ioread32(ioaddr + ((mmd_address & 0xff) << 2));
+       return value;
+}
+
+static void xmdio_write(void *ioaddr, unsigned int mmd,
+                       unsigned int reg, unsigned int value)
+{
+       unsigned int mmd_address;
+
+       mmd_address = (mmd << 16) | ((reg) & 0xffff);
+       iowrite32(mmd_address >> 8, ioaddr + (PCS_MMD_SELECT << 2));
+       iowrite32(value, ioaddr + ((mmd_address & 0xff) << 2));
+}
+
+int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev)
+{
+       struct vfio_platform_region *xgmac_regs = &vdev->regions[0];
+       struct vfio_platform_region *xpcs_regs = &vdev->regions[1];
+       u32 dma_mr_value, pcs_value, value;
+       unsigned int count;
+
+       if (!xgmac_regs->ioaddr) {
+               xgmac_regs->ioaddr =
+                       ioremap_nocache(xgmac_regs->addr, xgmac_regs->size);
+               if (!xgmac_regs->ioaddr)
+                       return -ENOMEM;
+       }
+       if (!xpcs_regs->ioaddr) {
+               xpcs_regs->ioaddr =
+                       ioremap_nocache(xpcs_regs->addr, xpcs_regs->size);
+               if (!xpcs_regs->ioaddr)
+                       return -ENOMEM;
+       }
+
+       /* reset the PHY through MDIO*/
+       pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1);
+       pcs_value |= MDIO_CTRL1_RESET;
+       xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_PCS, MDIO_CTRL1, pcs_value);
+
+       count = 50;
+       do {
+               msleep(20);
+               pcs_value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_PCS,
+                                       MDIO_CTRL1);
+       } while ((pcs_value & MDIO_CTRL1_RESET) && --count);
+
+       if (pcs_value & MDIO_CTRL1_RESET)
+               pr_warn("%s XGBE PHY reset timeout\n", __func__);
+
+       /* disable auto-negotiation */
+       value = xmdio_read(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1);
+       value &= ~MDIO_AN_CTRL1_ENABLE;
+       xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_CTRL1, value);
+
+       /* disable AN IRQ */
+       xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+
+       /* clear AN IRQ */
+       xmdio_write(xpcs_regs->ioaddr, MDIO_MMD_AN, MDIO_AN_INT, 0);
+
+       /* MAC software reset */
+       dma_mr_value = ioread32(xgmac_regs->ioaddr + DMA_MR);
+       dma_mr_value |= 0x1;
+       iowrite32(dma_mr_value, xgmac_regs->ioaddr + DMA_MR);
+
+       usleep_range(10, 15);
+
+       count = 2000;
+       while (count-- && (ioread32(xgmac_regs->ioaddr + DMA_MR) & 1))
+               usleep_range(500, 600);
+
+       if (!count)
+               pr_warn("%s MAC SW reset failed\n", __func__);
+
+       return 0;
+}
+
+module_vfio_reset_handler("amd,xgbe-seattle-v1a", vfio_platform_amdxgbe_reset);
+
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Eric Auger <eric.auger@linaro.org>");
+MODULE_DESCRIPTION("Reset support for AMD xgbe vfio platform device");
index 619dc7d22082407771dc257a3a1a61d5a70e77eb..e3d3d948e6618c9732db62740031f2d8a42c5d0c 100644 (file)
@@ -30,8 +30,6 @@
 #define DRIVER_AUTHOR   "Eric Auger <eric.auger@linaro.org>"
 #define DRIVER_DESC     "Reset support for Calxeda xgmac vfio platform device"
 
-#define CALXEDAXGMAC_COMPAT "calxeda,hb-xgmac"
-
 /* XGMAC Register definitions */
 #define XGMAC_CONTROL           0x00000000      /* MAC Configuration */
 
@@ -61,24 +59,25 @@ static inline void xgmac_mac_disable(void __iomem *ioaddr)
 
 int vfio_platform_calxedaxgmac_reset(struct vfio_platform_device *vdev)
 {
-       struct vfio_platform_region reg = vdev->regions[0];
+       struct vfio_platform_region *reg = &vdev->regions[0];
 
-       if (!reg.ioaddr) {
-               reg.ioaddr =
-                       ioremap_nocache(reg.addr, reg.size);
-               if (!reg.ioaddr)
+       if (!reg->ioaddr) {
+               reg->ioaddr =
+                       ioremap_nocache(reg->addr, reg->size);
+               if (!reg->ioaddr)
                        return -ENOMEM;
        }
 
        /* disable IRQ */
-       writel(0, reg.ioaddr + XGMAC_DMA_INTR_ENA);
+       writel(0, reg->ioaddr + XGMAC_DMA_INTR_ENA);
 
        /* Disable the MAC core */
-       xgmac_mac_disable(reg.ioaddr);
+       xgmac_mac_disable(reg->ioaddr);
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(vfio_platform_calxedaxgmac_reset);
+
+module_vfio_reset_handler("calxeda,hb-xgmac", vfio_platform_calxedaxgmac_reset);
 
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL v2");
index ff0331f72526b30e2d84a46f7895b97e5478b690..a66479bd0edf968c8209b384264052f79a6ec272 100644 (file)
@@ -67,6 +67,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
        vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
        vdev->get_resource = get_amba_resource;
        vdev->get_irq = get_amba_irq;
+       vdev->parent_module = THIS_MODULE;
 
        ret = vfio_platform_probe_common(vdev, &adev->dev);
        if (ret) {
index cef645c8399679056b130ad19c3dbcbe2e480549..f1625dcfbb23d49d6b0586977a203462df0e75a5 100644 (file)
@@ -65,6 +65,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
        vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
        vdev->get_resource = get_platform_resource;
        vdev->get_irq = get_platform_irq;
+       vdev->parent_module = THIS_MODULE;
 
        ret = vfio_platform_probe_common(vdev, &pdev->dev);
        if (ret)
index e43efb5e92bf5bf6115d2df38391979d898b465d..a1c50d63079200ce90741ccd55e60bc703c73eb2 100644 (file)
 
 #include "vfio_platform_private.h"
 
-static DEFINE_MUTEX(driver_lock);
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
+#define DRIVER_DESC     "VFIO platform base module"
 
-static const struct vfio_platform_reset_combo reset_lookup_table[] = {
-       {
-               .compat = "calxeda,hb-xgmac",
-               .reset_function_name = "vfio_platform_calxedaxgmac_reset",
-               .module_name = "vfio-platform-calxedaxgmac",
-       },
-};
+static LIST_HEAD(reset_list);
+static DEFINE_MUTEX(driver_lock);
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev,
-                                   struct device *dev)
+static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
+                                       struct module **module)
 {
-       const char *compat;
-       int (*reset)(struct vfio_platform_device *);
-       int ret, i;
-
-       ret = device_property_read_string(dev, "compatible", &compat);
-       if (ret)
-               return;
-
-       for (i = 0 ; i < ARRAY_SIZE(reset_lookup_table); i++) {
-               if (!strcmp(reset_lookup_table[i].compat, compat)) {
-                       request_module(reset_lookup_table[i].module_name);
-                       reset = __symbol_get(
-                               reset_lookup_table[i].reset_function_name);
-                       if (reset) {
-                               vdev->reset = reset;
-                               return;
-                       }
+       struct vfio_platform_reset_node *iter;
+       vfio_platform_reset_fn_t reset_fn = NULL;
+
+       mutex_lock(&driver_lock);
+       list_for_each_entry(iter, &reset_list, link) {
+               if (!strcmp(iter->compat, compat) &&
+                       try_module_get(iter->owner)) {
+                       *module = iter->owner;
+                       reset_fn = iter->reset;
+                       break;
                }
        }
+       mutex_unlock(&driver_lock);
+       return reset_fn;
+}
+
+static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+{
+       char modname[256];
+
+       vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+                                               &vdev->reset_module);
+       if (!vdev->reset) {
+               snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
+               request_module(modname);
+               vdev->reset = vfio_platform_lookup_reset(vdev->compat,
+                                                        &vdev->reset_module);
+       }
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
        if (vdev->reset)
-               symbol_put_addr(vdev->reset);
+               module_put(vdev->reset_module);
 }
 
 static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
@@ -138,15 +144,19 @@ static void vfio_platform_release(void *device_data)
        mutex_lock(&driver_lock);
 
        if (!(--vdev->refcnt)) {
-               if (vdev->reset)
+               if (vdev->reset) {
+                       dev_info(vdev->device, "reset\n");
                        vdev->reset(vdev);
+               } else {
+                       dev_warn(vdev->device, "no reset function found!\n");
+               }
                vfio_platform_regions_cleanup(vdev);
                vfio_platform_irq_cleanup(vdev);
        }
 
        mutex_unlock(&driver_lock);
 
-       module_put(THIS_MODULE);
+       module_put(vdev->parent_module);
 }
 
 static int vfio_platform_open(void *device_data)
@@ -154,7 +164,7 @@ static int vfio_platform_open(void *device_data)
        struct vfio_platform_device *vdev = device_data;
        int ret;
 
-       if (!try_module_get(THIS_MODULE))
+       if (!try_module_get(vdev->parent_module))
                return -ENODEV;
 
        mutex_lock(&driver_lock);
@@ -168,8 +178,12 @@ static int vfio_platform_open(void *device_data)
                if (ret)
                        goto err_irq;
 
-               if (vdev->reset)
+               if (vdev->reset) {
+                       dev_info(vdev->device, "reset\n");
                        vdev->reset(vdev);
+               } else {
+                       dev_warn(vdev->device, "no reset function found!\n");
+               }
        }
 
        vdev->refcnt++;
@@ -307,17 +321,17 @@ static long vfio_platform_ioctl(void *device_data,
        return -ENOTTY;
 }
 
-static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg,
                                       char __user *buf, size_t count,
                                       loff_t off)
 {
        unsigned int done = 0;
 
-       if (!reg.ioaddr) {
-               reg.ioaddr =
-                       ioremap_nocache(reg.addr, reg.size);
+       if (!reg->ioaddr) {
+               reg->ioaddr =
+                       ioremap_nocache(reg->addr, reg->size);
 
-               if (!reg.ioaddr)
+               if (!reg->ioaddr)
                        return -ENOMEM;
        }
 
@@ -327,7 +341,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
                if (count >= 4 && !(off % 4)) {
                        u32 val;
 
-                       val = ioread32(reg.ioaddr + off);
+                       val = ioread32(reg->ioaddr + off);
                        if (copy_to_user(buf, &val, 4))
                                goto err;
 
@@ -335,7 +349,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
                } else if (count >= 2 && !(off % 2)) {
                        u16 val;
 
-                       val = ioread16(reg.ioaddr + off);
+                       val = ioread16(reg->ioaddr + off);
                        if (copy_to_user(buf, &val, 2))
                                goto err;
 
@@ -343,7 +357,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
                } else {
                        u8 val;
 
-                       val = ioread8(reg.ioaddr + off);
+                       val = ioread8(reg->ioaddr + off);
                        if (copy_to_user(buf, &val, 1))
                                goto err;
 
@@ -376,7 +390,7 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
                return -EINVAL;
 
        if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
-               return vfio_platform_read_mmio(vdev->regions[index],
+               return vfio_platform_read_mmio(&vdev->regions[index],
                                                        buf, count, off);
        else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
                return -EINVAL; /* not implemented */
@@ -384,17 +398,17 @@ static ssize_t vfio_platform_read(void *device_data, char __user *buf,
        return -EINVAL;
 }
 
-static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg,
                                        const char __user *buf, size_t count,
                                        loff_t off)
 {
        unsigned int done = 0;
 
-       if (!reg.ioaddr) {
-               reg.ioaddr =
-                       ioremap_nocache(reg.addr, reg.size);
+       if (!reg->ioaddr) {
+               reg->ioaddr =
+                       ioremap_nocache(reg->addr, reg->size);
 
-               if (!reg.ioaddr)
+               if (!reg->ioaddr)
                        return -ENOMEM;
        }
 
@@ -406,7 +420,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
 
                        if (copy_from_user(&val, buf, 4))
                                goto err;
-                       iowrite32(val, reg.ioaddr + off);
+                       iowrite32(val, reg->ioaddr + off);
 
                        filled = 4;
                } else if (count >= 2 && !(off % 2)) {
@@ -414,7 +428,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
 
                        if (copy_from_user(&val, buf, 2))
                                goto err;
-                       iowrite16(val, reg.ioaddr + off);
+                       iowrite16(val, reg->ioaddr + off);
 
                        filled = 2;
                } else {
@@ -422,7 +436,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
 
                        if (copy_from_user(&val, buf, 1))
                                goto err;
-                       iowrite8(val, reg.ioaddr + off);
+                       iowrite8(val, reg->ioaddr + off);
 
                        filled = 1;
                }
@@ -452,7 +466,7 @@ static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
                return -EINVAL;
 
        if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
-               return vfio_platform_write_mmio(vdev->regions[index],
+               return vfio_platform_write_mmio(&vdev->regions[index],
                                                        buf, count, off);
        else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
                return -EINVAL; /* not implemented */
@@ -539,6 +553,14 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
        if (!vdev)
                return -EINVAL;
 
+       ret = device_property_read_string(dev, "compatible", &vdev->compat);
+       if (ret) {
+               pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
+               return -EINVAL;
+       }
+
+       vdev->device = dev;
+
        group = iommu_group_get(dev);
        if (!group) {
                pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
@@ -551,7 +573,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
                return ret;
        }
 
-       vfio_platform_get_reset(vdev, dev);
+       vfio_platform_get_reset(vdev);
 
        mutex_init(&vdev->igate);
 
@@ -573,3 +595,34 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
        return vdev;
 }
 EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
+
+void __vfio_platform_register_reset(struct vfio_platform_reset_node *node)
+{
+       mutex_lock(&driver_lock);
+       list_add(&node->link, &reset_list);
+       mutex_unlock(&driver_lock);
+}
+EXPORT_SYMBOL_GPL(__vfio_platform_register_reset);
+
+void vfio_platform_unregister_reset(const char *compat,
+                                   vfio_platform_reset_fn_t fn)
+{
+       struct vfio_platform_reset_node *iter, *temp;
+
+       mutex_lock(&driver_lock);
+       list_for_each_entry_safe(iter, temp, &reset_list, link) {
+               if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
+                       list_del(&iter->link);
+                       break;
+               }
+       }
+
+       mutex_unlock(&driver_lock);
+
+}
+EXPORT_SYMBOL_GPL(vfio_platform_unregister_reset);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
index 88bba57b30a8b28eefded76cd3ec3f9cd8912001..46d4750f43a8dccd574ea21f4fe53ecef4ec764c 100644 (file)
@@ -185,6 +185,7 @@ static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
        int ret;
 
        if (irq->trigger) {
+               irq_clear_status_flags(irq->hwirq, IRQ_NOAUTOEN);
                free_irq(irq->hwirq, irq);
                kfree(irq->name);
                eventfd_ctx_put(irq->trigger);
index 1c9b3d59543c1f32e60737be19bb46824bbebda3..42816dd280cb98ac4e27fabced74c2d9aa1df3d7 100644 (file)
@@ -56,6 +56,10 @@ struct vfio_platform_device {
        u32                             num_irqs;
        int                             refcnt;
        struct mutex                    igate;
+       struct module                   *parent_module;
+       const char                      *compat;
+       struct module                   *reset_module;
+       struct device                   *device;
 
        /*
         * These fields should be filled by the bus specific binder
@@ -70,10 +74,13 @@ struct vfio_platform_device {
        int     (*reset)(struct vfio_platform_device *vdev);
 };
 
-struct vfio_platform_reset_combo {
-       const char *compat;
-       const char *reset_function_name;
-       const char *module_name;
+typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
+
+struct vfio_platform_reset_node {
+       struct list_head link;
+       char *compat;
+       struct module *owner;
+       vfio_platform_reset_fn_t reset;
 };
 
 extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
@@ -89,4 +96,29 @@ extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
                                        unsigned start, unsigned count,
                                        void *data);
 
+extern void __vfio_platform_register_reset(struct vfio_platform_reset_node *n);
+extern void vfio_platform_unregister_reset(const char *compat,
+                                          vfio_platform_reset_fn_t fn);
+#define vfio_platform_register_reset(__compat, __reset)                \
+static struct vfio_platform_reset_node __reset ## _node = {    \
+       .owner = THIS_MODULE,                                   \
+       .compat = __compat,                                     \
+       .reset = __reset,                                       \
+};                                                             \
+__vfio_platform_register_reset(&__reset ## _node)
+
+#define module_vfio_reset_handler(compat, reset)               \
+MODULE_ALIAS("vfio-reset:" compat);                            \
+static int __init reset ## _module_init(void)                  \
+{                                                              \
+       vfio_platform_register_reset(compat, reset);            \
+       return 0;                                               \
+};                                                             \
+static void __exit reset ## _module_exit(void)                 \
+{                                                              \
+       vfio_platform_unregister_reset(compat, reset);          \
+};                                                             \
+module_init(reset ## _module_init);                            \
+module_exit(reset ## _module_exit)
+
 #endif /* VFIO_PLATFORM_PRIVATE_H */
index 563c510f285c47d2a7362a4da8729fdc38e1dee0..de632da2e22f60d4eee042631821c1a4a9b7e558 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pci.h>
 #include <linux/rwsem.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -61,6 +62,7 @@ struct vfio_container {
        struct rw_semaphore             group_lock;
        struct vfio_iommu_driver        *iommu_driver;
        void                            *iommu_data;
+       bool                            noiommu;
 };
 
 struct vfio_unbound_dev {
@@ -83,6 +85,7 @@ struct vfio_group {
        struct list_head                unbound_list;
        struct mutex                    unbound_lock;
        atomic_t                        opened;
+       bool                            noiommu;
 };
 
 struct vfio_device {
@@ -94,6 +97,147 @@ struct vfio_device {
        void                            *device_data;
 };
 
+#ifdef CONFIG_VFIO_NOIOMMU
+static bool noiommu __read_mostly;
+module_param_named(enable_unsafe_noiommu_support,
+                  noiommu, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode.  This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel.  If you do not know what this is for, step away. (default: false)");
+#endif
+
+/*
+ * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
+ * and remove functions, any use cases other than acquiring the first
+ * reference for the purpose of calling vfio_add_group_dev() or removing
+ * that symmetric reference after vfio_del_group_dev() should use the raw
+ * iommu_group_{get,put} functions.  In particular, vfio_iommu_group_put()
+ * removes the device from the dummy group and cannot be nested.
+ */
+struct iommu_group *vfio_iommu_group_get(struct device *dev)
+{
+       struct iommu_group *group;
+       int __maybe_unused ret;
+
+       group = iommu_group_get(dev);
+
+#ifdef CONFIG_VFIO_NOIOMMU
+       /*
+        * With noiommu enabled, an IOMMU group will be created for a device
+        * that doesn't already have one and doesn't have an iommu_ops on their
+        * bus.  We use iommu_present() again in the main code to detect these
+        * fake groups.
+        */
+       if (group || !noiommu || iommu_present(dev->bus))
+               return group;
+
+       group = iommu_group_alloc();
+       if (IS_ERR(group))
+               return NULL;
+
+       iommu_group_set_name(group, "vfio-noiommu");
+       ret = iommu_group_add_device(group, dev);
+       iommu_group_put(group);
+       if (ret)
+               return NULL;
+
+       /*
+        * Where to taint?  At this point we've added an IOMMU group for a
+        * device that is not backed by iommu_ops, therefore any iommu_
+        * callback using iommu_ops can legitimately Oops.  So, while we may
+        * be about to give a DMA capable device to a user without IOMMU
+        * protection, which is clearly taint-worthy, let's go ahead and do
+        * it here.
+        */
+       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+       dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n");
+#endif
+
+       return group;
+}
+EXPORT_SYMBOL_GPL(vfio_iommu_group_get);
+
+void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
+{
+#ifdef CONFIG_VFIO_NOIOMMU
+       if (!iommu_present(dev->bus))
+               iommu_group_remove_device(dev);
+#endif
+
+       iommu_group_put(group);
+}
+EXPORT_SYMBOL_GPL(vfio_iommu_group_put);
+
+#ifdef CONFIG_VFIO_NOIOMMU
+static void *vfio_noiommu_open(unsigned long arg)
+{
+       if (arg != VFIO_NOIOMMU_IOMMU)
+               return ERR_PTR(-EINVAL);
+       if (!capable(CAP_SYS_RAWIO))
+               return ERR_PTR(-EPERM);
+
+       return NULL;
+}
+
+static void vfio_noiommu_release(void *iommu_data)
+{
+}
+
+static long vfio_noiommu_ioctl(void *iommu_data,
+                              unsigned int cmd, unsigned long arg)
+{
+       if (cmd == VFIO_CHECK_EXTENSION)
+               return arg == VFIO_NOIOMMU_IOMMU ? 1 : 0;
+
+       return -ENOTTY;
+}
+
+static int vfio_iommu_present(struct device *dev, void *unused)
+{
+       return iommu_present(dev->bus) ? 1 : 0;
+}
+
+static int vfio_noiommu_attach_group(void *iommu_data,
+                                    struct iommu_group *iommu_group)
+{
+       return iommu_group_for_each_dev(iommu_group, NULL,
+                                       vfio_iommu_present) ? -EINVAL : 0;
+}
+
+static void vfio_noiommu_detach_group(void *iommu_data,
+                                     struct iommu_group *iommu_group)
+{
+}
+
+static struct vfio_iommu_driver_ops vfio_noiommu_ops = {
+       .name = "vfio-noiommu",
+       .owner = THIS_MODULE,
+       .open = vfio_noiommu_open,
+       .release = vfio_noiommu_release,
+       .ioctl = vfio_noiommu_ioctl,
+       .attach_group = vfio_noiommu_attach_group,
+       .detach_group = vfio_noiommu_detach_group,
+};
+
+static struct vfio_iommu_driver vfio_noiommu_driver = {
+       .ops = &vfio_noiommu_ops,
+};
+
+/*
+ * Wrap IOMMU drivers, the noiommu driver is the one and only driver for
+ * noiommu groups (and thus containers) and not available for normal groups.
+ */
+#define vfio_for_each_iommu_driver(con, pos)                           \
+       for (pos = con->noiommu ? &vfio_noiommu_driver :                \
+            list_first_entry(&vfio.iommu_drivers_list,                 \
+                             struct vfio_iommu_driver, vfio_next);     \
+            (con->noiommu ? pos != NULL :                              \
+                       &pos->vfio_next != &vfio.iommu_drivers_list);   \
+             pos = con->noiommu ? NULL : list_next_entry(pos, vfio_next))
+#else
+#define vfio_for_each_iommu_driver(con, pos)                           \
+       list_for_each_entry(pos, &vfio.iommu_drivers_list, vfio_next)
+#endif
+
+
 /**
  * IOMMU driver registration
  */
@@ -198,7 +342,8 @@ static void vfio_group_unlock_and_free(struct vfio_group *group)
 /**
  * Group objects - create, release, get, put, search
  */
-static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
+static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
+                                           bool noiommu)
 {
        struct vfio_group *group, *tmp;
        struct device *dev;
@@ -216,6 +361,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
        atomic_set(&group->container_users, 0);
        atomic_set(&group->opened, 0);
        group->iommu_group = iommu_group;
+       group->noiommu = noiommu;
 
        group->nb.notifier_call = vfio_iommu_group_notifier;
 
@@ -251,7 +397,8 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 
        dev = device_create(vfio.class, NULL,
                            MKDEV(MAJOR(vfio.group_devt), minor),
-                           group, "%d", iommu_group_id(iommu_group));
+                           group, "%s%d", noiommu ? "noiommu-" : "",
+                           iommu_group_id(iommu_group));
        if (IS_ERR(dev)) {
                vfio_free_group_minor(minor);
                vfio_group_unlock_and_free(group);
@@ -438,16 +585,33 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group,
 }
 
 /*
- * Whitelist some drivers that we know are safe (no dma) or just sit on
- * a device.  It's not always practical to leave a device within a group
- * driverless as it could get re-bound to something unsafe.
+ * Some drivers, like pci-stub, are only used to prevent other drivers from
+ * claiming a device and are therefore perfectly legitimate for a user owned
+ * group.  The pci-stub driver has no dependencies on DMA or the IOVA mapping
+ * of the device, but it does prevent the user from having direct access to
+ * the device, which is useful in some circumstances.
+ *
+ * We also assume that we can include PCI interconnect devices, ie. bridges.
+ * IOMMU grouping on PCI necessitates that if we lack isolation on a bridge
+ * then all of the downstream devices will be part of the same IOMMU group as
+ * the bridge.  Thus, if placing the bridge into the user owned IOVA space
+ * breaks anything, it only does so for user owned devices downstream.  Note
+ * that error notification via MSI can be affected for platforms that handle
+ * MSI within the same IOVA space as DMA.
  */
-static const char * const vfio_driver_whitelist[] = { "pci-stub", "pcieport" };
+static const char * const vfio_driver_whitelist[] = { "pci-stub" };
 
-static bool vfio_whitelisted_driver(struct device_driver *drv)
+static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
 {
        int i;
 
+       if (dev_is_pci(dev)) {
+               struct pci_dev *pdev = to_pci_dev(dev);
+
+               if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+                       return true;
+       }
+
        for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) {
                if (!strcmp(drv->name, vfio_driver_whitelist[i]))
                        return true;
@@ -462,6 +626,7 @@ static bool vfio_whitelisted_driver(struct device_driver *drv)
  *  - driver-less
  *  - bound to a vfio driver
  *  - bound to a whitelisted driver
+ *  - a PCI interconnect device
  *
  * We use two methods to determine whether a device is bound to a vfio
  * driver.  The first is to test whether the device exists in the vfio
@@ -486,7 +651,7 @@ static int vfio_dev_viable(struct device *dev, void *data)
        }
        mutex_unlock(&group->unbound_lock);
 
-       if (!ret || !drv || vfio_whitelisted_driver(drv))
+       if (!ret || !drv || vfio_dev_whitelisted(dev, drv))
                return 0;
 
        device = vfio_group_get_device(group, dev);
@@ -621,7 +786,8 @@ int vfio_add_group_dev(struct device *dev,
 
        group = vfio_group_get_from_iommu(iommu_group);
        if (!group) {
-               group = vfio_create_group(iommu_group);
+               group = vfio_create_group(iommu_group,
+                                         !iommu_present(dev->bus));
                if (IS_ERR(group)) {
                        iommu_group_put(iommu_group);
                        return PTR_ERR(group);
@@ -692,11 +858,12 @@ EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
 static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
                                                     char *buf)
 {
-       struct vfio_device *device;
+       struct vfio_device *it, *device = NULL;
 
        mutex_lock(&group->device_lock);
-       list_for_each_entry(device, &group->device_list, group_next) {
-               if (!strcmp(dev_name(device->dev), buf)) {
+       list_for_each_entry(it, &group->device_list, group_next) {
+               if (!strcmp(dev_name(it->dev), buf)) {
+                       device = it;
                        vfio_device_get(device);
                        break;
                }
@@ -832,8 +999,7 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
                 */
                if (!driver) {
                        mutex_lock(&vfio.iommu_drivers_lock);
-                       list_for_each_entry(driver, &vfio.iommu_drivers_list,
-                                           vfio_next) {
+                       vfio_for_each_iommu_driver(container, driver) {
                                if (!try_module_get(driver->ops->owner))
                                        continue;
 
@@ -902,7 +1068,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
        }
 
        mutex_lock(&vfio.iommu_drivers_lock);
-       list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) {
+       vfio_for_each_iommu_driver(container, driver) {
                void *data;
 
                if (!try_module_get(driver->ops->owner))
@@ -1167,6 +1333,9 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
        if (atomic_read(&group->container_users))
                return -EINVAL;
 
+       if (group->noiommu && !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
        f = fdget(container_fd);
        if (!f.file)
                return -EBADF;
@@ -1182,6 +1351,13 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
 
        down_write(&container->group_lock);
 
+       /* Real groups and fake groups cannot mix */
+       if (!list_empty(&container->group_list) &&
+           container->noiommu != group->noiommu) {
+               ret = -EPERM;
+               goto unlock_out;
+       }
+
        driver = container->iommu_driver;
        if (driver) {
                ret = driver->ops->attach_group(container->iommu_data,
@@ -1191,6 +1367,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
        }
 
        group->container = container;
+       container->noiommu = group->noiommu;
        list_add(&group->container_next, &container->group_list);
 
        /* Get a reference on the container and mark a user within the group */
@@ -1221,6 +1398,9 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
            !group->container->iommu_driver || !vfio_group_viable(group))
                return -EINVAL;
 
+       if (group->noiommu && !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
        device = vfio_device_get_from_name(group, buf);
        if (!device)
                return -ENODEV;
@@ -1263,6 +1443,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
 
        fd_install(ret, filep);
 
+       if (group->noiommu)
+               dev_warn(device->dev, "vfio-noiommu device opened by user "
+                        "(%s:%d)\n", current->comm, task_pid_nr(current));
+
        return ret;
 }
 
@@ -1351,6 +1535,11 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
        if (!group)
                return -ENODEV;
 
+       if (group->noiommu && !capable(CAP_SYS_RAWIO)) {
+               vfio_group_put(group);
+               return -EPERM;
+       }
+
        /* Do we need multiple instances of the group open?  Seems not. */
        opened = atomic_cmpxchg(&group->opened, 0, 1);
        if (opened) {
@@ -1513,6 +1702,11 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
        if (!atomic_inc_not_zero(&group->container_users))
                return ERR_PTR(-EINVAL);
 
+       if (group->noiommu) {
+               atomic_dec(&group->container_users);
+               return ERR_PTR(-EPERM);
+       }
+
        if (!group->container->iommu_driver ||
                        !vfio_group_viable(group)) {
                atomic_dec(&group->container_users);
index 57d8c37a002b0e0b8d49891536b8ddfab64afc6b..59d47cb638d5d18aac6700157ecc9be918772f91 100644 (file)
@@ -403,13 +403,26 @@ static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
 static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu)
 {
        struct vfio_domain *domain;
-       unsigned long bitmap = PAGE_MASK;
+       unsigned long bitmap = ULONG_MAX;
 
        mutex_lock(&iommu->lock);
        list_for_each_entry(domain, &iommu->domain_list, next)
                bitmap &= domain->domain->ops->pgsize_bitmap;
        mutex_unlock(&iommu->lock);
 
+       /*
+        * In case the IOMMU supports page sizes smaller than PAGE_SIZE
+        * we pretend PAGE_SIZE is supported and hide sub-PAGE_SIZE sizes.
+        * That way the user will be able to map/unmap buffers whose size/
+        * start address is aligned with PAGE_SIZE. Pinning code uses that
+        * granularity while iommu driver can use the sub-PAGE_SIZE size
+        * to map the buffer.
+        */
+       if (bitmap & ~PAGE_MASK) {
+               bitmap &= PAGE_MASK;
+               bitmap |= PAGE_SIZE;
+       }
+
        return bitmap;
 }
 
index e25a23692822c16ce26f7a2b9b9f7f96153a6563..29cfc57d496e9497ebcf7bd5c5bd07a083bd91dc 100644 (file)
@@ -42,8 +42,6 @@
 #include <scsi/scsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/configfs_macros.h>
 #include <linux/vhost.h>
 #include <linux/virtio_scsi.h>
 #include <linux/llist.h>
@@ -1684,11 +1682,10 @@ static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
        }
 }
 
-static ssize_t vhost_scsi_tpg_attrib_store_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       const char *page,
-       size_t count)
+static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_store(
+               struct config_item *item, const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
        unsigned long val;
@@ -1707,19 +1704,20 @@ static ssize_t vhost_scsi_tpg_attrib_store_fabric_prot_type(
        return count;
 }
 
-static ssize_t vhost_scsi_tpg_attrib_show_fabric_prot_type(
-       struct se_portal_group *se_tpg,
-       char *page)
+static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_show(
+               struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = attrib_to_tpg(item);
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
 
        return sprintf(page, "%d\n", tpg->tv_fabric_prot_type);
 }
-TF_TPG_ATTRIB_ATTR(vhost_scsi, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR(vhost_scsi_tpg_attrib_, fabric_prot_type);
 
 static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = {
-       &vhost_scsi_tpg_attrib_fabric_prot_type.attr,
+       &vhost_scsi_tpg_attrib_attr_fabric_prot_type,
        NULL,
 };
 
@@ -1867,9 +1865,9 @@ static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
        return 0;
 }
 
-static ssize_t vhost_scsi_tpg_show_nexus(struct se_portal_group *se_tpg,
-                                       char *page)
+static ssize_t vhost_scsi_tpg_nexus_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
        struct vhost_scsi_nexus *tv_nexus;
@@ -1888,10 +1886,10 @@ static ssize_t vhost_scsi_tpg_show_nexus(struct se_portal_group *se_tpg,
        return ret;
 }
 
-static ssize_t vhost_scsi_tpg_store_nexus(struct se_portal_group *se_tpg,
-                                        const char *page,
-                                        size_t count)
+static ssize_t vhost_scsi_tpg_nexus_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
        struct vhost_scsi_tport *tport_wwn = tpg->tport;
@@ -1966,10 +1964,10 @@ static ssize_t vhost_scsi_tpg_store_nexus(struct se_portal_group *se_tpg,
        return count;
 }
 
-TF_TPG_BASE_ATTR(vhost_scsi, nexus, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(vhost_scsi_tpg_, nexus);
 
 static struct configfs_attribute *vhost_scsi_tpg_attrs[] = {
-       &vhost_scsi_tpg_nexus.attr,
+       &vhost_scsi_tpg_attr_nexus,
        NULL,
 };
 
@@ -2105,18 +2103,17 @@ static void vhost_scsi_drop_tport(struct se_wwn *wwn)
 }
 
 static ssize_t
-vhost_scsi_wwn_show_attr_version(struct target_fabric_configfs *tf,
-                               char *page)
+vhost_scsi_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "TCM_VHOST fabric module %s on %s/%s"
                "on "UTS_RELEASE"\n", VHOST_SCSI_VERSION, utsname()->sysname,
                utsname()->machine);
 }
 
-TF_WWN_ATTR_RO(vhost_scsi, version);
+CONFIGFS_ATTR_RO(vhost_scsi_wwn_, version);
 
 static struct configfs_attribute *vhost_scsi_wwn_attrs[] = {
-       &vhost_scsi_wwn_version.attr,
+       &vhost_scsi_wwn_attr_version,
        NULL,
 };
 
index 7a8a6c6952e92b7fd2b659e1e2e0f4cbd2c39919..1c427beffadd97b3e95522fc9236193006d58fcc 100644 (file)
@@ -446,7 +446,7 @@ config MAX63XX_WATCHDOG
 
 config IMX2_WDT
        tristate "IMX2+ Watchdog"
-       depends on ARCH_MXC
+       depends on ARCH_MXC || ARCH_LAYERSCAPE
        select REGMAP_MMIO
        select WATCHDOG_CORE
        help
index 6ad9df948711080ca3c87464d0195bdd3c0d9feb..b751f43d76ed5c9d8e168389a1238b9218bee46f 100644 (file)
@@ -123,6 +123,7 @@ static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
 
        reg = readl(wdt_base + WDT_MODE);
        reg &= ~WDT_MODE_EN;
+       reg |= WDT_MODE_KEY;
        iowrite32(reg, wdt_base + WDT_MODE);
 
        return 0;
index d96bee017fd3caa2fbcde961cc3ba9941b34c341..6f17c935a6cf86b1fcb47856532a8d6374bd0d82 100644 (file)
@@ -205,7 +205,7 @@ static int omap_wdt_set_timeout(struct watchdog_device *wdog,
 
 static unsigned int omap_wdt_get_timeleft(struct watchdog_device *wdog)
 {
-       struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog);
+       struct omap_wdt_dev *wdev = to_omap_wdt_dev(wdog);
        void __iomem *base = wdev->base;
        u32 value;
 
index 4224b3ec83a5515dc76a57507ec81122dd9316e1..313cd1c6fda0efcfa03897f1d23fc18b138e3779 100644 (file)
@@ -80,7 +80,7 @@ static unsigned int heartbeat = DEFAULT_HEARTBEAT;
 
 static DEFINE_SPINLOCK(io_lock);
 static void __iomem    *wdt_base;
-struct clk             *wdt_clk;
+static struct clk      *wdt_clk;
 
 static int pnx4008_wdt_start(struct watchdog_device *wdd)
 {
@@ -161,7 +161,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
        if (IS_ERR(wdt_clk))
                return PTR_ERR(wdt_clk);
 
-       ret = clk_enable(wdt_clk);
+       ret = clk_prepare_enable(wdt_clk);
        if (ret)
                return ret;
 
@@ -184,7 +184,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev)
        return 0;
 
 disable_clk:
-       clk_disable(wdt_clk);
+       clk_disable_unprepare(wdt_clk);
        return ret;
 }
 
@@ -192,7 +192,7 @@ static int pnx4008_wdt_remove(struct platform_device *pdev)
 {
        watchdog_unregister_device(&pnx4008_wdd);
 
-       clk_disable(wdt_clk);
+       clk_disable_unprepare(wdt_clk);
 
        return 0;
 }
index 7f97cdd53f29624f6c732b0e44c0448a856c8a5c..9ec57608da82931e6f2a913246825ff9be11e034 100644 (file)
@@ -140,8 +140,10 @@ static int tegra_wdt_set_timeout(struct watchdog_device *wdd,
 {
        wdd->timeout = timeout;
 
-       if (watchdog_active(wdd))
+       if (watchdog_active(wdd)) {
+               tegra_wdt_stop(wdd);
                return tegra_wdt_start(wdd);
+       }
 
        return 0;
 }
index 91bf55a2002497eca6de68258515484ba9f13efa..20e2bba10400910cfbd86a68d3d6f988b9d77dec 100644 (file)
@@ -224,7 +224,7 @@ static int wdt_keepalive(void)
 
 static int wdt_set_timeout(int t)
 {
-       int tmrval;
+       unsigned int tmrval;
 
        /*
         * Convert seconds to watchdog counter time units, rounding up.
index 849500e4e14d14af7dd29fe7737d77d62f87a36d..524c22146429d7c87acc8682976031c2f8a727d6 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/irq.h>
 #include <asm/idle.h>
 #include <asm/io_apic.h>
+#include <asm/i8259.h>
 #include <asm/xen/pci.h>
 #endif
 #include <asm/sync_bitops.h>
@@ -420,7 +421,7 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
                return xen_allocate_irq_dynamic();
 
        /* Legacy IRQ descriptors are already allocated by the arch. */
-       if (gsi < NR_IRQS_LEGACY)
+       if (gsi < nr_legacy_irqs())
                irq = gsi;
        else
                irq = irq_alloc_desc_at(gsi, -1);
@@ -446,7 +447,7 @@ static void xen_free_irq(unsigned irq)
        kfree(info);
 
        /* Legacy IRQ descriptors are managed by the arch. */
-       if (irq < NR_IRQS_LEGACY)
+       if (irq < nr_legacy_irqs())
                return;
 
        irq_free_desc(irq);
index 00f40f051d95668b01ebf6b4c17e6f0e90912198..38272ad245516c272ab571bed1a5c962f4a0e808 100644 (file)
@@ -49,6 +49,8 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/cpu.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
 struct per_user_data {
        struct mutex bind_mutex; /* serialize bind/unbind operations */
        struct rb_root evtchns;
+       unsigned int nr_evtchns;
 
        /* Notification ring, accessed via /dev/xen/evtchn. */
-#define EVTCHN_RING_SIZE     (PAGE_SIZE / sizeof(evtchn_port_t))
-#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+       unsigned int ring_size;
        evtchn_port_t *ring;
        unsigned int ring_cons, ring_prod, ring_overflow;
        struct mutex ring_cons_mutex; /* protect against concurrent readers */
@@ -80,10 +82,41 @@ struct user_evtchn {
        bool enabled;
 };
 
+static evtchn_port_t *evtchn_alloc_ring(unsigned int size)
+{
+       evtchn_port_t *ring;
+       size_t s = size * sizeof(*ring);
+
+       ring = kmalloc(s, GFP_KERNEL);
+       if (!ring)
+               ring = vmalloc(s);
+
+       return ring;
+}
+
+static void evtchn_free_ring(evtchn_port_t *ring)
+{
+       kvfree(ring);
+}
+
+static unsigned int evtchn_ring_offset(struct per_user_data *u,
+                                      unsigned int idx)
+{
+       return idx & (u->ring_size - 1);
+}
+
+static evtchn_port_t *evtchn_ring_entry(struct per_user_data *u,
+                                       unsigned int idx)
+{
+       return u->ring + evtchn_ring_offset(u, idx);
+}
+
 static int add_evtchn(struct per_user_data *u, struct user_evtchn *evtchn)
 {
        struct rb_node **new = &(u->evtchns.rb_node), *parent = NULL;
 
+       u->nr_evtchns++;
+
        while (*new) {
                struct user_evtchn *this;
 
@@ -107,6 +140,7 @@ static int add_evtchn(struct per_user_data *u, struct user_evtchn *evtchn)
 
 static void del_evtchn(struct per_user_data *u, struct user_evtchn *evtchn)
 {
+       u->nr_evtchns--;
        rb_erase(&evtchn->node, &u->evtchns);
        kfree(evtchn);
 }
@@ -144,8 +178,8 @@ static irqreturn_t evtchn_interrupt(int irq, void *data)
 
        spin_lock(&u->ring_prod_lock);
 
-       if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
-               u->ring[EVTCHN_RING_MASK(u->ring_prod)] = evtchn->port;
+       if ((u->ring_prod - u->ring_cons) < u->ring_size) {
+               *evtchn_ring_entry(u, u->ring_prod) = evtchn->port;
                wmb(); /* Ensure ring contents visible */
                if (u->ring_cons == u->ring_prod++) {
                        wake_up_interruptible(&u->evtchn_wait);
@@ -200,10 +234,10 @@ static ssize_t evtchn_read(struct file *file, char __user *buf,
        }
 
        /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
-       if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
-               bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
+       if (((c ^ p) & u->ring_size) != 0) {
+               bytes1 = (u->ring_size - evtchn_ring_offset(u, c)) *
                        sizeof(evtchn_port_t);
-               bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
+               bytes2 = evtchn_ring_offset(u, p) * sizeof(evtchn_port_t);
        } else {
                bytes1 = (p - c) * sizeof(evtchn_port_t);
                bytes2 = 0;
@@ -219,7 +253,7 @@ static ssize_t evtchn_read(struct file *file, char __user *buf,
 
        rc = -EFAULT;
        rmb(); /* Ensure that we see the port before we copy it. */
-       if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+       if (copy_to_user(buf, evtchn_ring_entry(u, c), bytes1) ||
            ((bytes2 != 0) &&
             copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
                goto unlock_out;
@@ -278,6 +312,66 @@ static ssize_t evtchn_write(struct file *file, const char __user *buf,
        return rc;
 }
 
+static int evtchn_resize_ring(struct per_user_data *u)
+{
+       unsigned int new_size;
+       evtchn_port_t *new_ring, *old_ring;
+       unsigned int p, c;
+
+       /*
+        * Ensure the ring is large enough to capture all possible
+        * events. i.e., one free slot for each bound event.
+        */
+       if (u->nr_evtchns <= u->ring_size)
+               return 0;
+
+       if (u->ring_size == 0)
+               new_size = 64;
+       else
+               new_size = 2 * u->ring_size;
+
+       new_ring = evtchn_alloc_ring(new_size);
+       if (!new_ring)
+               return -ENOMEM;
+
+       old_ring = u->ring;
+
+       /*
+        * Access to the ring contents is serialized by either the
+        * prod /or/ cons lock so take both when resizing.
+        */
+       mutex_lock(&u->ring_cons_mutex);
+       spin_lock_irq(&u->ring_prod_lock);
+
+       /*
+        * Copy the old ring contents to the new ring.
+        *
+        * If the ring contents crosses the end of the current ring,
+        * it needs to be copied in two chunks.
+        *
+        * +---------+    +------------------+
+        * |34567  12| -> |       1234567    |
+        * +-----p-c-+    +------------------+
+        */
+       p = evtchn_ring_offset(u, u->ring_prod);
+       c = evtchn_ring_offset(u, u->ring_cons);
+       if (p < c) {
+               memcpy(new_ring + c, u->ring + c, (u->ring_size - c) * sizeof(*u->ring));
+               memcpy(new_ring + u->ring_size, u->ring, p * sizeof(*u->ring));
+       } else
+               memcpy(new_ring + c, u->ring + c, (p - c) * sizeof(*u->ring));
+
+       u->ring = new_ring;
+       u->ring_size = new_size;
+
+       spin_unlock_irq(&u->ring_prod_lock);
+       mutex_unlock(&u->ring_cons_mutex);
+
+       evtchn_free_ring(old_ring);
+
+       return 0;
+}
+
 static int evtchn_bind_to_user(struct per_user_data *u, int port)
 {
        struct user_evtchn *evtchn;
@@ -305,6 +399,10 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port)
        if (rc < 0)
                goto err;
 
+       rc = evtchn_resize_ring(u);
+       if (rc < 0)
+               goto err;
+
        rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, 0,
                                       u->name, evtchn);
        if (rc < 0)
@@ -503,13 +601,6 @@ static int evtchn_open(struct inode *inode, struct file *filp)
 
        init_waitqueue_head(&u->evtchn_wait);
 
-       u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
-       if (u->ring == NULL) {
-               kfree(u->name);
-               kfree(u);
-               return -ENOMEM;
-       }
-
        mutex_init(&u->bind_mutex);
        mutex_init(&u->ring_cons_mutex);
        spin_lock_init(&u->ring_prod_lock);
@@ -532,7 +623,7 @@ static int evtchn_release(struct inode *inode, struct file *filp)
                evtchn_unbind_from_user(u, evtchn);
        }
 
-       free_page((unsigned long)u->ring);
+       evtchn_free_ring(u->ring);
        kfree(u->name);
        kfree(u);
 
index 2ea0b3b2a91d2585a2d37f8ead07f08f32c79826..1be5dd048622f6c8c4f9aa805514b9fd5b5c5d7b 100644 (file)
@@ -804,7 +804,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 
        vma->vm_ops = &gntdev_vmops;
 
-       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
 
        if (use_ptemod)
                vma->vm_flags |= VM_DONTCOPY;
index 9eeefd7cad41127dcade5d81c06647218abeaccc..43bcae852546ad2e5021b4a1d326dda375ae4023 100644 (file)
@@ -53,7 +53,6 @@
 
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
 
 #include <asm/hypervisor.h>
 
@@ -1438,9 +1437,10 @@ static void scsiback_aborted_task(struct se_cmd *se_cmd)
 {
 }
 
-static ssize_t scsiback_tpg_param_show_alias(struct se_portal_group *se_tpg,
+static ssize_t scsiback_tpg_param_alias_show(struct config_item *item,
                                             char *page)
 {
+       struct se_portal_group *se_tpg = param_to_tpg(item);
        struct scsiback_tpg *tpg = container_of(se_tpg, struct scsiback_tpg,
                                                se_tpg);
        ssize_t rb;
@@ -1452,9 +1452,10 @@ static ssize_t scsiback_tpg_param_show_alias(struct se_portal_group *se_tpg,
        return rb;
 }
 
-static ssize_t scsiback_tpg_param_store_alias(struct se_portal_group *se_tpg,
+static ssize_t scsiback_tpg_param_alias_store(struct config_item *item,
                                              const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = param_to_tpg(item);
        struct scsiback_tpg *tpg = container_of(se_tpg, struct scsiback_tpg,
                                                se_tpg);
        int len;
@@ -1474,10 +1475,10 @@ static ssize_t scsiback_tpg_param_store_alias(struct se_portal_group *se_tpg,
        return count;
 }
 
-TF_TPG_PARAM_ATTR(scsiback, alias, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(scsiback_tpg_param_, alias);
 
 static struct configfs_attribute *scsiback_param_attrs[] = {
-       &scsiback_tpg_param_alias.attr,
+       &scsiback_tpg_param_attr_alias,
        NULL,
 };
 
@@ -1585,9 +1586,9 @@ static int scsiback_drop_nexus(struct scsiback_tpg *tpg)
        return 0;
 }
 
-static ssize_t scsiback_tpg_show_nexus(struct se_portal_group *se_tpg,
-                                       char *page)
+static ssize_t scsiback_tpg_nexus_show(struct config_item *item, char *page)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct scsiback_tpg *tpg = container_of(se_tpg,
                                struct scsiback_tpg, se_tpg);
        struct scsiback_nexus *tv_nexus;
@@ -1606,10 +1607,10 @@ static ssize_t scsiback_tpg_show_nexus(struct se_portal_group *se_tpg,
        return ret;
 }
 
-static ssize_t scsiback_tpg_store_nexus(struct se_portal_group *se_tpg,
-                                        const char *page,
-                                        size_t count)
+static ssize_t scsiback_tpg_nexus_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct se_portal_group *se_tpg = to_tpg(item);
        struct scsiback_tpg *tpg = container_of(se_tpg,
                                struct scsiback_tpg, se_tpg);
        struct scsiback_tport *tport_wwn = tpg->tport;
@@ -1681,26 +1682,25 @@ static ssize_t scsiback_tpg_store_nexus(struct se_portal_group *se_tpg,
        return count;
 }
 
-TF_TPG_BASE_ATTR(scsiback, nexus, S_IRUGO | S_IWUSR);
+CONFIGFS_ATTR(scsiback_tpg_, nexus);
 
 static struct configfs_attribute *scsiback_tpg_attrs[] = {
-       &scsiback_tpg_nexus.attr,
+       &scsiback_tpg_attr_nexus,
        NULL,
 };
 
 static ssize_t
-scsiback_wwn_show_attr_version(struct target_fabric_configfs *tf,
-                               char *page)
+scsiback_wwn_version_show(struct config_item *item, char *page)
 {
        return sprintf(page, "xen-pvscsi fabric module %s on %s/%s on "
                UTS_RELEASE"\n",
                VSCSI_VERSION, utsname()->sysname, utsname()->machine);
 }
 
-TF_WWN_ATTR_RO(scsiback, version);
+CONFIGFS_ATTR_RO(scsiback_wwn_, version);
 
 static struct configfs_attribute *scsiback_wwn_attrs[] = {
-       &scsiback_wwn_version.attr,
+       &scsiback_wwn_attr_version,
        NULL,
 };
 
index ff7be98f84f2412359bba865b34314fc62dd6ae9..9619ccadd2fcd9717bb3e186d8de78db932b9653 100644 (file)
@@ -10,10 +10,7 @@ obj-$(CONFIG_9P_FS) := 9p.o
        vfs_dentry.o \
        v9fs.o \
        fid.o  \
-       xattr.o \
-       xattr_user.o \
-       xattr_trusted.o
+       xattr.o
 
 9p-$(CONFIG_9P_FSCACHE) += cache.o
 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o
-9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o
index 31c010372660154f6665782e89cea669b8457d29..a7e28890f5efb4ec8729fc9de4f09e16d4fb91bd 100644 (file)
@@ -212,26 +212,9 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
        return 0;
 }
 
-static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
-                              void *buffer, size_t size, int type)
-{
-       char *full_name;
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               full_name =  POSIX_ACL_XATTR_ACCESS;
-               break;
-       case ACL_TYPE_DEFAULT:
-               full_name = POSIX_ACL_XATTR_DEFAULT;
-               break;
-       default:
-               BUG();
-       }
-       return v9fs_xattr_get(dentry, full_name, buffer, size);
-}
-
-static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
-                             void *buffer, size_t size, int type)
+static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
+                             struct dentry *dentry, const char *name,
+                             void *buffer, size_t size)
 {
        struct v9fs_session_info *v9ses;
        struct posix_acl *acl;
@@ -245,9 +228,9 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
         * We allow set/get/list of acl when access=client is not specified
         */
        if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-               return v9fs_remote_get_acl(dentry, name, buffer, size, type);
+               return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
 
-       acl = v9fs_get_cached_acl(d_inode(dentry), type);
+       acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -258,29 +241,9 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
        return error;
 }
 
-static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
-                             const void *value, size_t size,
-                             int flags, int type)
-{
-       char *full_name;
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               full_name =  POSIX_ACL_XATTR_ACCESS;
-               break;
-       case ACL_TYPE_DEFAULT:
-               full_name = POSIX_ACL_XATTR_DEFAULT;
-               break;
-       default:
-               BUG();
-       }
-       return v9fs_xattr_set(dentry, full_name, value, size, flags);
-}
-
-
-static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
-                             const void *value, size_t size,
-                             int flags, int type)
+static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
+                             struct dentry *dentry, const char *name,
+                             const void *value, size_t size, int flags)
 {
        int retval;
        struct posix_acl *acl;
@@ -296,8 +259,8 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
         * xattr value. We leave it to the server to validate
         */
        if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
-               return v9fs_remote_set_acl(dentry, name,
-                                          value, size, flags, type);
+               return v9fs_xattr_set(dentry, handler->prefix, value, size,
+                                     flags);
 
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
@@ -316,9 +279,8 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
        } else
                acl = NULL;
 
-       switch (type) {
+       switch (handler->flags) {
        case ACL_TYPE_ACCESS:
-               name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
                        umode_t mode = inode->i_mode;
                        retval = posix_acl_equiv_mode(acl, &mode);
@@ -349,7 +311,6 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
                }
                break;
        case ACL_TYPE_DEFAULT:
-               name = POSIX_ACL_XATTR_DEFAULT;
                if (!S_ISDIR(inode->i_mode)) {
                        retval = acl ? -EINVAL : 0;
                        goto err_out;
@@ -358,9 +319,9 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
        default:
                BUG();
        }
-       retval = v9fs_xattr_set(dentry, name, value, size, flags);
+       retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
        if (!retval)
-               set_cached_acl(inode, type, acl);
+               set_cached_acl(inode, handler->flags, acl);
 err_out:
        posix_acl_release(acl);
        return retval;
index 0cf44b6cccd6ee7dd131033845c7619ad778ab89..e3d026ac382eb482c9840140466b946aa554dd78 100644 (file)
@@ -137,6 +137,48 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
        return v9fs_xattr_get(dentry, NULL, buffer, buffer_size);
 }
 
+static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
+                                 struct dentry *dentry, const char *name,
+                                 void *buffer, size_t size)
+{
+       const char *full_name = xattr_full_name(handler, name);
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return v9fs_xattr_get(dentry, full_name, buffer, size);
+}
+
+static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
+                                 struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags)
+{
+       const char *full_name = xattr_full_name(handler, name);
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+       return v9fs_xattr_set(dentry, full_name, value, size, flags);
+}
+
+static struct xattr_handler v9fs_xattr_user_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .get    = v9fs_xattr_handler_get,
+       .set    = v9fs_xattr_handler_set,
+};
+
+static struct xattr_handler v9fs_xattr_trusted_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .get    = v9fs_xattr_handler_get,
+       .set    = v9fs_xattr_handler_set,
+};
+
+#ifdef CONFIG_9P_FS_SECURITY
+static struct xattr_handler v9fs_xattr_security_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .get    = v9fs_xattr_handler_get,
+       .set    = v9fs_xattr_handler_set,
+};
+#endif
+
 const struct xattr_handler *v9fs_xattr_handlers[] = {
        &v9fs_xattr_user_handler,
        &v9fs_xattr_trusted_handler,
index d3e2ea3840bedf2f6e3a2f1b0274172810a17ff8..c63c3bea5de550d87159e55ccedb0f057fcebedb 100644 (file)
@@ -19,9 +19,6 @@
 #include <net/9p/client.h>
 
 extern const struct xattr_handler *v9fs_xattr_handlers[];
-extern struct xattr_handler v9fs_xattr_user_handler;
-extern struct xattr_handler v9fs_xattr_trusted_handler;
-extern struct xattr_handler v9fs_xattr_security_handler;
 extern const struct xattr_handler v9fs_xattr_acl_access_handler;
 extern const struct xattr_handler v9fs_xattr_acl_default_handler;
 
diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c
deleted file mode 100644 (file)
index cb247a1..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_security_get(struct dentry *dentry, const char *name,
-                       void *buffer, size_t size, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-       memcpy(full_name+prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-       kfree(full_name);
-       return retval;
-}
-
-static int v9fs_xattr_security_set(struct dentry *dentry, const char *name,
-                       const void *value, size_t size, int flags, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len);
-       memcpy(full_name + prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-       kfree(full_name);
-       return retval;
-}
-
-struct xattr_handler v9fs_xattr_security_handler = {
-       .prefix = XATTR_SECURITY_PREFIX,
-       .get    = v9fs_xattr_security_get,
-       .set    = v9fs_xattr_security_set,
-};
diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c
deleted file mode 100644 (file)
index e30d33b..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name,
-                       void *buffer, size_t size, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-       memcpy(full_name+prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-       kfree(full_name);
-       return retval;
-}
-
-static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name,
-                       const void *value, size_t size, int flags, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len);
-       memcpy(full_name + prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-       kfree(full_name);
-       return retval;
-}
-
-struct xattr_handler v9fs_xattr_trusted_handler = {
-       .prefix = XATTR_TRUSTED_PREFIX,
-       .get    = v9fs_xattr_trusted_get,
-       .set    = v9fs_xattr_trusted_set,
-};
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c
deleted file mode 100644 (file)
index d0b701b..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright IBM Corporation, 2010
- * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include "xattr.h"
-
-static int v9fs_xattr_user_get(struct dentry *dentry, const char *name,
-                       void *buffer, size_t size, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_USER_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-       memcpy(full_name+prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_get(dentry, full_name, buffer, size);
-       kfree(full_name);
-       return retval;
-}
-
-static int v9fs_xattr_user_set(struct dentry *dentry, const char *name,
-                       const void *value, size_t size, int flags, int type)
-{
-       int retval;
-       char *full_name;
-       size_t name_len;
-       size_t prefix_len = XATTR_USER_PREFIX_LEN;
-
-       if (name == NULL)
-               return -EINVAL;
-
-       if (strcmp(name, "") == 0)
-               return -EINVAL;
-
-       name_len = strlen(name);
-       full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL);
-       if (!full_name)
-               return -ENOMEM;
-       memcpy(full_name, XATTR_USER_PREFIX, prefix_len);
-       memcpy(full_name + prefix_len, name, name_len);
-       full_name[prefix_len + name_len] = '\0';
-
-       retval = v9fs_xattr_set(dentry, full_name, value, size, flags);
-       kfree(full_name);
-       return retval;
-}
-
-struct xattr_handler v9fs_xattr_user_handler = {
-       .prefix = XATTR_USER_PREFIX,
-       .get    = v9fs_xattr_user_get,
-       .set    = v9fs_xattr_user_set,
-};
index da3f32f1a4e4bd9f43a6d5a81c192d43612aa8e1..6ce72d8d1ee12473bfcb1e550967be2a0a1c8d27 100644 (file)
@@ -46,6 +46,12 @@ config FS_DAX
          or if unsure, say N.  Saying Y will increase the size of the kernel
          by about 5kB.
 
+config FS_DAX_PMD
+       bool
+       default FS_DAX
+       depends on FS_DAX
+       depends on BROKEN
+
 endif # BLOCK
 
 # Posix ACL utility routines
index 0a793c7930eba290ab50555ea3def8fd1d99203b..c25639e907bd21a194aecedc6c60a93fb4994375 100644 (file)
@@ -50,12 +50,21 @@ struct block_device *I_BDEV(struct inode *inode)
 }
 EXPORT_SYMBOL(I_BDEV);
 
-static void bdev_write_inode(struct inode *inode)
+static void bdev_write_inode(struct block_device *bdev)
 {
+       struct inode *inode = bdev->bd_inode;
+       int ret;
+
        spin_lock(&inode->i_lock);
        while (inode->i_state & I_DIRTY) {
                spin_unlock(&inode->i_lock);
-               WARN_ON_ONCE(write_inode_now(inode, true));
+               ret = write_inode_now(inode, true);
+               if (ret) {
+                       char name[BDEVNAME_SIZE];
+                       pr_warn_ratelimited("VFS: Dirty inode writeback failed "
+                                           "for block device %s (err=%d).\n",
+                                           bdevname(bdev, name), ret);
+               }
                spin_lock(&inode->i_lock);
        }
        spin_unlock(&inode->i_lock);
@@ -381,9 +390,17 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,
                        struct page *page)
 {
        const struct block_device_operations *ops = bdev->bd_disk->fops;
+       int result = -EOPNOTSUPP;
+
        if (!ops->rw_page || bdev_get_integrity(bdev))
-               return -EOPNOTSUPP;
-       return ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
+               return result;
+
+       result = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
+       if (result)
+               return result;
+       result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
+       blk_queue_exit(bdev->bd_queue);
+       return result;
 }
 EXPORT_SYMBOL_GPL(bdev_read_page);
 
@@ -412,14 +429,20 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
        int result;
        int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE;
        const struct block_device_operations *ops = bdev->bd_disk->fops;
+
        if (!ops->rw_page || bdev_get_integrity(bdev))
                return -EOPNOTSUPP;
+       result = blk_queue_enter(bdev->bd_queue, GFP_KERNEL);
+       if (result)
+               return result;
+
        set_page_writeback(page);
        result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw);
        if (result)
                end_page_writeback(page);
        else
                unlock_page(page);
+       blk_queue_exit(bdev->bd_queue);
        return result;
 }
 EXPORT_SYMBOL_GPL(bdev_write_page);
@@ -1504,7 +1527,7 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                 * ->release can cause the queue to disappear, so flush all
                 * dirty data before.
                 */
-               bdev_write_inode(bdev->bd_inode);
+               bdev_write_inode(bdev);
        }
        if (bdev->bd_contains == bdev) {
                if (disk->fops->release)
index 6dcdb2ec921185ae350aa0f2ff49cd65eaa0d500..d453d62ab0c6e322b3c0df0a05b20daa6751d5ad 100644 (file)
@@ -355,7 +355,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
 
        index = srcu_read_lock(&fs_info->subvol_srcu);
 
-       root = btrfs_read_fs_root_no_name(fs_info, &root_key);
+       root = btrfs_get_fs_root(fs_info, &root_key, false);
        if (IS_ERR(root)) {
                srcu_read_unlock(&fs_info->subvol_srcu, index);
                ret = PTR_ERR(root);
index 8c58191249cc14c33c376bb0c8c0a469cb95b894..35489e7129a7e8de9d0232279d41d3bbd19ae1df 100644 (file)
@@ -3416,6 +3416,7 @@ int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
 struct btrfs_block_group_cache *btrfs_lookup_block_group(
                                                 struct btrfs_fs_info *info,
                                                 u64 bytenr);
+void btrfs_get_block_group(struct btrfs_block_group_cache *cache);
 void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
 int get_block_group_index(struct btrfs_block_group_cache *cache);
 struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
@@ -3479,6 +3480,9 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, u64 bytes_used,
                           u64 type, u64 chunk_objectid, u64 chunk_offset,
                           u64 size);
+struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
+                               struct btrfs_fs_info *fs_info,
+                               const u64 chunk_offset);
 int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, u64 group_start,
                             struct extent_map *em);
index 640598c0d0e7585ff125b1a63ed9e74c2c42eaed..974be09e7556ca3f342cac89357364f4ce3cc016 100644 (file)
@@ -3780,6 +3780,9 @@ void close_ctree(struct btrfs_root *root)
        fs_info->closing = 1;
        smp_mb();
 
+       /* wait for the qgroup rescan worker to stop */
+       btrfs_qgroup_wait_for_completion(fs_info);
+
        /* wait for the uuid_scan task to finish */
        down(&fs_info->uuid_tree_rescan_sem);
        /* avoid complains from lockdep et al., set sem back to initial state */
index 99a8e57da8a11fbbdcbc0d833a687d79629200cc..4b89680a192338c7a70a4c909e3c4374abe41284 100644 (file)
@@ -124,7 +124,7 @@ static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
        return (cache->flags & bits) == bits;
 }
 
-static void btrfs_get_block_group(struct btrfs_block_group_cache *cache)
+void btrfs_get_block_group(struct btrfs_block_group_cache *cache)
 {
        atomic_inc(&cache->count);
 }
@@ -5915,19 +5915,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                        set_extent_dirty(info->pinned_extents,
                                         bytenr, bytenr + num_bytes - 1,
                                         GFP_NOFS | __GFP_NOFAIL);
-                       /*
-                        * No longer have used bytes in this block group, queue
-                        * it for deletion.
-                        */
-                       if (old_val == 0) {
-                               spin_lock(&info->unused_bgs_lock);
-                               if (list_empty(&cache->bg_list)) {
-                                       btrfs_get_block_group(cache);
-                                       list_add_tail(&cache->bg_list,
-                                                     &info->unused_bgs);
-                               }
-                               spin_unlock(&info->unused_bgs_lock);
-                       }
                }
 
                spin_lock(&trans->transaction->dirty_bgs_lock);
@@ -5939,6 +5926,22 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                }
                spin_unlock(&trans->transaction->dirty_bgs_lock);
 
+               /*
+                * No longer have used bytes in this block group, queue it for
+                * deletion. We do this after adding the block group to the
+                * dirty list to avoid races between cleaner kthread and space
+                * cache writeout.
+                */
+               if (!alloc && old_val == 0) {
+                       spin_lock(&info->unused_bgs_lock);
+                       if (list_empty(&cache->bg_list)) {
+                               btrfs_get_block_group(cache);
+                               list_add_tail(&cache->bg_list,
+                                             &info->unused_bgs);
+                       }
+                       spin_unlock(&info->unused_bgs_lock);
+               }
+
                btrfs_put_block_group(cache);
                total -= num_bytes;
                bytenr += num_bytes;
@@ -8105,21 +8108,47 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
 }
 
 /*
- * TODO: Modify related function to add related node/leaf to dirty_extent_root,
- * for later qgroup accounting.
- *
- * Current, this function does nothing.
+ * These may not be seen by the usual inc/dec ref code so we have to
+ * add them here.
  */
+static int record_one_subtree_extent(struct btrfs_trans_handle *trans,
+                                    struct btrfs_root *root, u64 bytenr,
+                                    u64 num_bytes)
+{
+       struct btrfs_qgroup_extent_record *qrecord;
+       struct btrfs_delayed_ref_root *delayed_refs;
+
+       qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS);
+       if (!qrecord)
+               return -ENOMEM;
+
+       qrecord->bytenr = bytenr;
+       qrecord->num_bytes = num_bytes;
+       qrecord->old_roots = NULL;
+
+       delayed_refs = &trans->transaction->delayed_refs;
+       spin_lock(&delayed_refs->lock);
+       if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
+               kfree(qrecord);
+       spin_unlock(&delayed_refs->lock);
+
+       return 0;
+}
+
 static int account_leaf_items(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              struct extent_buffer *eb)
 {
        int nr = btrfs_header_nritems(eb);
-       int i, extent_type;
+       int i, extent_type, ret;
        struct btrfs_key key;
        struct btrfs_file_extent_item *fi;
        u64 bytenr, num_bytes;
 
+       /* We can be called directly from walk_up_proc() */
+       if (!root->fs_info->quota_enabled)
+               return 0;
+
        for (i = 0; i < nr; i++) {
                btrfs_item_key_to_cpu(eb, &key, i);
 
@@ -8138,6 +8167,10 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,
                        continue;
 
                num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi);
+
+               ret = record_one_subtree_extent(trans, root, bytenr, num_bytes);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -8206,8 +8239,6 @@ static int adjust_slots_upwards(struct btrfs_root *root,
 
 /*
  * root_eb is the subtree root and is locked before this function is called.
- * TODO: Modify this function to mark all (including complete shared node)
- * to dirty_extent_root to allow it get accounted in qgroup.
  */
 static int account_shared_subtree(struct btrfs_trans_handle *trans,
                                  struct btrfs_root *root,
@@ -8285,6 +8316,11 @@ static int account_shared_subtree(struct btrfs_trans_handle *trans,
                        btrfs_tree_read_lock(eb);
                        btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                        path->locks[level] = BTRFS_READ_LOCK_BLOCKING;
+
+                       ret = record_one_subtree_extent(trans, root, child_bytenr,
+                                                       root->nodesize);
+                       if (ret)
+                               goto out;
                }
 
                if (level == 0) {
@@ -10256,6 +10292,47 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        return ret;
 }
 
+struct btrfs_trans_handle *
+btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info,
+                                    const u64 chunk_offset)
+{
+       struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree;
+       struct extent_map *em;
+       struct map_lookup *map;
+       unsigned int num_items;
+
+       read_lock(&em_tree->lock);
+       em = lookup_extent_mapping(em_tree, chunk_offset, 1);
+       read_unlock(&em_tree->lock);
+       ASSERT(em && em->start == chunk_offset);
+
+       /*
+        * We need to reserve 3 + N units from the metadata space info in order
+        * to remove a block group (done at btrfs_remove_chunk() and at
+        * btrfs_remove_block_group()), which are used for:
+        *
+        * 1 unit for adding the free space inode's orphan (located in the tree
+        * of tree roots).
+        * 1 unit for deleting the block group item (located in the extent
+        * tree).
+        * 1 unit for deleting the free space item (located in tree of tree
+        * roots).
+        * N units for deleting N device extent items corresponding to each
+        * stripe (located in the device tree).
+        *
+        * In order to remove a block group we also need to reserve units in the
+        * system space info in order to update the chunk tree (update one or
+        * more device items and remove one chunk item), but this is done at
+        * btrfs_remove_chunk() through a call to check_system_chunk().
+        */
+       map = (struct map_lookup *)em->bdev;
+       num_items = 3 + map->num_stripes;
+       free_extent_map(em);
+
+       return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root,
+                                                          num_items, 1);
+}
+
 /*
  * Process the unused_bgs list and remove any that don't have any allocated
  * space inside of them.
@@ -10279,22 +10356,25 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                block_group = list_first_entry(&fs_info->unused_bgs,
                                               struct btrfs_block_group_cache,
                                               bg_list);
-               space_info = block_group->space_info;
                list_del_init(&block_group->bg_list);
+
+               space_info = block_group->space_info;
+
                if (ret || btrfs_mixed_space_info(space_info)) {
                        btrfs_put_block_group(block_group);
                        continue;
                }
                spin_unlock(&fs_info->unused_bgs_lock);
 
-               mutex_lock(&root->fs_info->delete_unused_bgs_mutex);
+               mutex_lock(&fs_info->delete_unused_bgs_mutex);
 
                /* Don't want to race with allocators so take the groups_sem */
                down_write(&space_info->groups_sem);
                spin_lock(&block_group->lock);
                if (block_group->reserved ||
                    btrfs_block_group_used(&block_group->item) ||
-                   block_group->ro) {
+                   block_group->ro ||
+                   list_is_singular(&block_group->list)) {
                        /*
                         * We want to bail if we made new allocations or have
                         * outstanding allocations in this block group.  We do
@@ -10319,8 +10399,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                 * Want to do this before we do anything else so we can recover
                 * properly if we fail to join the transaction.
                 */
-               /* 1 for btrfs_orphan_reserve_metadata() */
-               trans = btrfs_start_transaction(root, 1);
+               trans = btrfs_start_trans_remove_block_group(fs_info,
+                                                    block_group->key.objectid);
                if (IS_ERR(trans)) {
                        btrfs_dec_block_group_ro(root, block_group);
                        ret = PTR_ERR(trans);
@@ -10410,7 +10490,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
 end_trans:
                btrfs_end_transaction(trans, root);
 next:
-               mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
+               mutex_unlock(&fs_info->delete_unused_bgs_mutex);
                btrfs_put_block_group(block_group);
                spin_lock(&fs_info->unused_bgs_lock);
        }
index 6bd5ce9d75f0ab8eaca5a2f808bfaf5a66132742..72e73461c0643bbf128504c93a9c47dd377784aa 100644 (file)
@@ -756,8 +756,16 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
                }
 
                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
-               if (key.objectid > ino ||
-                   key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+
+               if (key.objectid > ino)
+                       break;
+               if (WARN_ON_ONCE(key.objectid < ino) ||
+                   key.type < BTRFS_EXTENT_DATA_KEY) {
+                       ASSERT(del_nr == 0);
+                       path->slots[0]++;
+                       goto next_slot;
+               }
+               if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
                        break;
 
                fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -776,8 +784,8 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans,
                                btrfs_file_extent_inline_len(leaf,
                                                     path->slots[0], fi);
                } else {
-                       WARN_ON(1);
-                       extent_end = search_start;
+                       /* can't happen */
+                       BUG();
                }
 
                /*
@@ -1874,8 +1882,13 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        struct btrfs_log_ctx ctx;
        int ret = 0;
        bool full_sync = 0;
-       const u64 len = end - start + 1;
+       u64 len;
 
+       /*
+        * The range length can be represented by u64, we have to do the typecasts
+        * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync()
+        */
+       len = (u64)end - (u64)start + 1;
        trace_btrfs_sync_file(file, datasync);
 
        /*
@@ -2063,8 +2076,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                        }
                }
                if (!full_sync) {
-                       ret = btrfs_wait_ordered_range(inode, start,
-                                                      end - start + 1);
+                       ret = btrfs_wait_ordered_range(inode, start, len);
                        if (ret) {
                                btrfs_end_transaction(trans, root);
                                goto out;
index 0e4f2bfcc37d083da90f381c0cfeeeb28f643cd2..a70c5790f8f5908f08f606d097fe33e6966af36b 100644 (file)
@@ -1304,8 +1304,14 @@ static noinline int run_delalloc_nocow(struct inode *inode,
                num_bytes = 0;
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 
-               if (found_key.objectid > ino ||
-                   found_key.type > BTRFS_EXTENT_DATA_KEY ||
+               if (found_key.objectid > ino)
+                       break;
+               if (WARN_ON_ONCE(found_key.objectid < ino) ||
+                   found_key.type < BTRFS_EXTENT_DATA_KEY) {
+                       path->slots[0]++;
+                       goto next_slot;
+               }
+               if (found_key.type > BTRFS_EXTENT_DATA_KEY ||
                    found_key.offset > end)
                        break;
 
@@ -4040,9 +4046,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
  */
 static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir)
 {
-       struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(dir)->root;
-       int ret;
 
        /*
         * 1 for the possible orphan item
@@ -4051,27 +4055,7 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir)
         * 1 for the inode ref
         * 1 for the inode
         */
-       trans = btrfs_start_transaction(root, 5);
-       if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
-               return trans;
-
-       if (PTR_ERR(trans) == -ENOSPC) {
-               u64 num_bytes = btrfs_calc_trans_metadata_size(root, 5);
-
-               trans = btrfs_start_transaction(root, 0);
-               if (IS_ERR(trans))
-                       return trans;
-               ret = btrfs_cond_migrate_bytes(root->fs_info,
-                                              &root->fs_info->trans_block_rsv,
-                                              num_bytes, 5);
-               if (ret) {
-                       btrfs_end_transaction(trans, root);
-                       return ERR_PTR(ret);
-               }
-               trans->block_rsv = &root->fs_info->trans_block_rsv;
-               trans->bytes_reserved = num_bytes;
-       }
-       return trans;
+       return btrfs_start_transaction_fallback_global_rsv(root, 5, 5);
 }
 
 static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
@@ -7503,6 +7487,28 @@ struct btrfs_dio_data {
        u64 reserve;
 };
 
+static void adjust_dio_outstanding_extents(struct inode *inode,
+                                          struct btrfs_dio_data *dio_data,
+                                          const u64 len)
+{
+       unsigned num_extents;
+
+       num_extents = (unsigned) div64_u64(len + BTRFS_MAX_EXTENT_SIZE - 1,
+                                          BTRFS_MAX_EXTENT_SIZE);
+       /*
+        * If we have an outstanding_extents count still set then we're
+        * within our reservation, otherwise we need to adjust our inode
+        * counter appropriately.
+        */
+       if (dio_data->outstanding_extents) {
+               dio_data->outstanding_extents -= num_extents;
+       } else {
+               spin_lock(&BTRFS_I(inode)->lock);
+               BTRFS_I(inode)->outstanding_extents += num_extents;
+               spin_unlock(&BTRFS_I(inode)->lock);
+       }
+}
+
 static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                                   struct buffer_head *bh_result, int create)
 {
@@ -7538,8 +7544,11 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
         * If this errors out it's because we couldn't invalidate pagecache for
         * this range and we need to fallback to buffered.
         */
-       if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create))
-               return -ENOTBLK;
+       if (lock_extent_direct(inode, lockstart, lockend, &cached_state,
+                              create)) {
+               ret = -ENOTBLK;
+               goto err;
+       }
 
        em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
        if (IS_ERR(em)) {
@@ -7657,19 +7666,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                if (start + len > i_size_read(inode))
                        i_size_write(inode, start + len);
 
-               /*
-                * If we have an outstanding_extents count still set then we're
-                * within our reservation, otherwise we need to adjust our inode
-                * counter appropriately.
-                */
-               if (dio_data->outstanding_extents) {
-                       (dio_data->outstanding_extents)--;
-               } else {
-                       spin_lock(&BTRFS_I(inode)->lock);
-                       BTRFS_I(inode)->outstanding_extents++;
-                       spin_unlock(&BTRFS_I(inode)->lock);
-               }
-
+               adjust_dio_outstanding_extents(inode, dio_data, len);
                btrfs_free_reserved_data_space(inode, start, len);
                WARN_ON(dio_data->reserve < len);
                dio_data->reserve -= len;
@@ -7696,8 +7693,17 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
 unlock_err:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
                         unlock_bits, 1, 0, &cached_state, GFP_NOFS);
+err:
        if (dio_data)
                current->journal_info = dio_data;
+       /*
+        * Compensate the delalloc release we do in btrfs_direct_IO() when we
+        * write less data then expected, so that we don't underflow our inode's
+        * outstanding extents counter.
+        */
+       if (create && dio_data)
+               adjust_dio_outstanding_extents(inode, dio_data, len);
+
        return ret;
 }
 
index 46476c226395e777045a2303a1ada87b9e4b4a78..5279fdae7142fbe3177a556a020ed1af3a7aa8f1 100644 (file)
@@ -993,9 +993,10 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        if (!fs_info->quota_root)
                goto out;
-       spin_lock(&fs_info->qgroup_lock);
        fs_info->quota_enabled = 0;
        fs_info->pending_quota_state = 0;
+       btrfs_qgroup_wait_for_completion(fs_info);
+       spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
        fs_info->quota_root = NULL;
        fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
@@ -1461,6 +1462,8 @@ struct btrfs_qgroup_extent_record
        struct btrfs_qgroup_extent_record *entry;
        u64 bytenr = record->bytenr;
 
+       assert_spin_locked(&delayed_refs->lock);
+
        while (*p) {
                parent_node = *p;
                entry = rb_entry(parent_node, struct btrfs_qgroup_extent_record,
@@ -2198,7 +2201,6 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
        int slot;
        int ret;
 
-       path->leave_spinning = 1;
        mutex_lock(&fs_info->qgroup_rescan_lock);
        ret = btrfs_search_slot_for_read(fs_info->extent_root,
                                         &fs_info->qgroup_rescan_progress,
@@ -2286,7 +2288,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
                goto out;
 
        err = 0;
-       while (!err) {
+       while (!err && !btrfs_fs_closing(fs_info)) {
                trans = btrfs_start_transaction(fs_info->fs_root, 0);
                if (IS_ERR(trans)) {
                        err = PTR_ERR(trans);
@@ -2307,7 +2309,8 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        btrfs_free_path(path);
 
        mutex_lock(&fs_info->qgroup_rescan_lock);
-       fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
+       if (!btrfs_fs_closing(fs_info))
+               fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
 
        if (err > 0 &&
            fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
@@ -2336,7 +2339,9 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        }
        btrfs_end_transaction(trans, fs_info->quota_root);
 
-       if (err >= 0) {
+       if (btrfs_fs_closing(fs_info)) {
+               btrfs_info(fs_info, "qgroup scan paused");
+       } else if (err >= 0) {
                btrfs_info(fs_info, "qgroup scan completed%s",
                        err > 0 ? " (inconsistency flag cleared)" : "");
        } else {
@@ -2384,12 +2389,11 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
        memset(&fs_info->qgroup_rescan_progress, 0,
                sizeof(fs_info->qgroup_rescan_progress));
        fs_info->qgroup_rescan_progress.objectid = progress_objectid;
+       init_completion(&fs_info->qgroup_rescan_completion);
 
        spin_unlock(&fs_info->qgroup_lock);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
-       init_completion(&fs_info->qgroup_rescan_completion);
-
        memset(&fs_info->qgroup_rescan_work, 0,
               sizeof(fs_info->qgroup_rescan_work));
        btrfs_init_work(&fs_info->qgroup_rescan_work,
index 550de89a8661af8fdb1c08783ffadde680c138ec..b091d94ceef68013e992161b0aaf31b47cc645dc 100644 (file)
@@ -248,14 +248,9 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check);
 static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
                                     struct scrub_block *sblocks_for_recheck);
 static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
-                               struct scrub_block *sblock, int is_metadata,
-                               int have_csum, u8 *csum, u64 generation,
-                               u16 csum_size, int retry_failed_mirror);
-static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
-                                        struct scrub_block *sblock,
-                                        int is_metadata, int have_csum,
-                                        const u8 *csum, u64 generation,
-                                        u16 csum_size);
+                               struct scrub_block *sblock,
+                               int retry_failed_mirror);
+static void scrub_recheck_block_checksum(struct scrub_block *sblock);
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good);
 static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
@@ -889,11 +884,9 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
        struct btrfs_fs_info *fs_info;
        u64 length;
        u64 logical;
-       u64 generation;
        unsigned int failed_mirror_index;
        unsigned int is_metadata;
        unsigned int have_csum;
-       u8 *csum;
        struct scrub_block *sblocks_for_recheck; /* holds one for each mirror */
        struct scrub_block *sblock_bad;
        int ret;
@@ -918,13 +911,11 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
        }
        length = sblock_to_check->page_count * PAGE_SIZE;
        logical = sblock_to_check->pagev[0]->logical;
-       generation = sblock_to_check->pagev[0]->generation;
        BUG_ON(sblock_to_check->pagev[0]->mirror_num < 1);
        failed_mirror_index = sblock_to_check->pagev[0]->mirror_num - 1;
        is_metadata = !(sblock_to_check->pagev[0]->flags &
                        BTRFS_EXTENT_FLAG_DATA);
        have_csum = sblock_to_check->pagev[0]->have_csum;
-       csum = sblock_to_check->pagev[0]->csum;
        dev = sblock_to_check->pagev[0]->dev;
 
        if (sctx->is_dev_replace && !is_metadata && !have_csum) {
@@ -987,8 +978,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
        sblock_bad = sblocks_for_recheck + failed_mirror_index;
 
        /* build and submit the bios for the failed mirror, check checksums */
-       scrub_recheck_block(fs_info, sblock_bad, is_metadata, have_csum,
-                           csum, generation, sctx->csum_size, 1);
+       scrub_recheck_block(fs_info, sblock_bad, 1);
 
        if (!sblock_bad->header_error && !sblock_bad->checksum_error &&
            sblock_bad->no_io_error_seen) {
@@ -1101,9 +1091,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
                sblock_other = sblocks_for_recheck + mirror_index;
 
                /* build and submit the bios, check checksums */
-               scrub_recheck_block(fs_info, sblock_other, is_metadata,
-                                   have_csum, csum, generation,
-                                   sctx->csum_size, 0);
+               scrub_recheck_block(fs_info, sblock_other, 0);
 
                if (!sblock_other->header_error &&
                    !sblock_other->checksum_error &&
@@ -1215,9 +1203,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
                         * is verified, but most likely the data comes out
                         * of the page cache.
                         */
-                       scrub_recheck_block(fs_info, sblock_bad,
-                                           is_metadata, have_csum, csum,
-                                           generation, sctx->csum_size, 1);
+                       scrub_recheck_block(fs_info, sblock_bad, 1);
                        if (!sblock_bad->header_error &&
                            !sblock_bad->checksum_error &&
                            sblock_bad->no_io_error_seen)
@@ -1318,6 +1304,9 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
        struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info;
        u64 length = original_sblock->page_count * PAGE_SIZE;
        u64 logical = original_sblock->pagev[0]->logical;
+       u64 generation = original_sblock->pagev[0]->generation;
+       u64 flags = original_sblock->pagev[0]->flags;
+       u64 have_csum = original_sblock->pagev[0]->have_csum;
        struct scrub_recover *recover;
        struct btrfs_bio *bbio;
        u64 sublen;
@@ -1372,6 +1361,7 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
 
                        sblock = sblocks_for_recheck + mirror_index;
                        sblock->sctx = sctx;
+
                        page = kzalloc(sizeof(*page), GFP_NOFS);
                        if (!page) {
 leave_nomem:
@@ -1383,7 +1373,15 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
                        }
                        scrub_page_get(page);
                        sblock->pagev[page_index] = page;
+                       page->sblock = sblock;
+                       page->flags = flags;
+                       page->generation = generation;
                        page->logical = logical;
+                       page->have_csum = have_csum;
+                       if (have_csum)
+                               memcpy(page->csum,
+                                      original_sblock->pagev[0]->csum,
+                                      sctx->csum_size);
 
                        scrub_stripe_index_and_offset(logical,
                                                      bbio->map_type,
@@ -1474,15 +1472,12 @@ static int scrub_submit_raid56_bio_wait(struct btrfs_fs_info *fs_info,
  * the pages that are errored in the just handled mirror can be repaired.
  */
 static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
-                               struct scrub_block *sblock, int is_metadata,
-                               int have_csum, u8 *csum, u64 generation,
-                               u16 csum_size, int retry_failed_mirror)
+                               struct scrub_block *sblock,
+                               int retry_failed_mirror)
 {
        int page_num;
 
        sblock->no_io_error_seen = 1;
-       sblock->header_error = 0;
-       sblock->checksum_error = 0;
 
        for (page_num = 0; page_num < sblock->page_count; page_num++) {
                struct bio *bio;
@@ -1518,9 +1513,7 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
        }
 
        if (sblock->no_io_error_seen)
-               scrub_recheck_block_checksum(fs_info, sblock, is_metadata,
-                                            have_csum, csum, generation,
-                                            csum_size);
+               scrub_recheck_block_checksum(sblock);
 
        return;
 }
@@ -1535,61 +1528,16 @@ static inline int scrub_check_fsid(u8 fsid[],
        return !ret;
 }
 
-static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
-                                        struct scrub_block *sblock,
-                                        int is_metadata, int have_csum,
-                                        const u8 *csum, u64 generation,
-                                        u16 csum_size)
+static void scrub_recheck_block_checksum(struct scrub_block *sblock)
 {
-       int page_num;
-       u8 calculated_csum[BTRFS_CSUM_SIZE];
-       u32 crc = ~(u32)0;
-       void *mapped_buffer;
-
-       WARN_ON(!sblock->pagev[0]->page);
-       if (is_metadata) {
-               struct btrfs_header *h;
-
-               mapped_buffer = kmap_atomic(sblock->pagev[0]->page);
-               h = (struct btrfs_header *)mapped_buffer;
-
-               if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h) ||
-                   !scrub_check_fsid(h->fsid, sblock->pagev[0]) ||
-                   memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid,
-                          BTRFS_UUID_SIZE)) {
-                       sblock->header_error = 1;
-               } else if (generation != btrfs_stack_header_generation(h)) {
-                       sblock->header_error = 1;
-                       sblock->generation_error = 1;
-               }
-               csum = h->csum;
-       } else {
-               if (!have_csum)
-                       return;
-
-               mapped_buffer = kmap_atomic(sblock->pagev[0]->page);
-       }
-
-       for (page_num = 0;;) {
-               if (page_num == 0 && is_metadata)
-                       crc = btrfs_csum_data(
-                               ((u8 *)mapped_buffer) + BTRFS_CSUM_SIZE,
-                               crc, PAGE_SIZE - BTRFS_CSUM_SIZE);
-               else
-                       crc = btrfs_csum_data(mapped_buffer, crc, PAGE_SIZE);
-
-               kunmap_atomic(mapped_buffer);
-               page_num++;
-               if (page_num >= sblock->page_count)
-                       break;
-               WARN_ON(!sblock->pagev[page_num]->page);
-
-               mapped_buffer = kmap_atomic(sblock->pagev[page_num]->page);
-       }
+       sblock->header_error = 0;
+       sblock->checksum_error = 0;
+       sblock->generation_error = 0;
 
-       btrfs_csum_final(crc, calculated_csum);
-       if (memcmp(calculated_csum, csum, csum_size))
-               sblock->checksum_error = 1;
+       if (sblock->pagev[0]->flags & BTRFS_EXTENT_FLAG_DATA)
+               scrub_checksum_data(sblock);
+       else
+               scrub_checksum_tree_block(sblock);
 }
 
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
@@ -1833,6 +1781,18 @@ static int scrub_checksum(struct scrub_block *sblock)
        u64 flags;
        int ret;
 
+       /*
+        * No need to initialize these stats currently,
+        * because this function only use return value
+        * instead of these stats value.
+        *
+        * Todo:
+        * always use stats
+        */
+       sblock->header_error = 0;
+       sblock->generation_error = 0;
+       sblock->checksum_error = 0;
+
        WARN_ON(sblock->page_count < 1);
        flags = sblock->pagev[0]->flags;
        ret = 0;
@@ -1858,7 +1818,6 @@ static int scrub_checksum_data(struct scrub_block *sblock)
        struct page *page;
        void *buffer;
        u32 crc = ~(u32)0;
-       int fail = 0;
        u64 len;
        int index;
 
@@ -1889,9 +1848,9 @@ static int scrub_checksum_data(struct scrub_block *sblock)
 
        btrfs_csum_final(crc, csum);
        if (memcmp(csum, on_disk_csum, sctx->csum_size))
-               fail = 1;
+               sblock->checksum_error = 1;
 
-       return fail;
+       return sblock->checksum_error;
 }
 
 static int scrub_checksum_tree_block(struct scrub_block *sblock)
@@ -1907,8 +1866,6 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
        u64 mapped_size;
        void *p;
        u32 crc = ~(u32)0;
-       int fail = 0;
-       int crc_fail = 0;
        u64 len;
        int index;
 
@@ -1923,19 +1880,20 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
         * a) don't have an extent buffer and
         * b) the page is already kmapped
         */
-
        if (sblock->pagev[0]->logical != btrfs_stack_header_bytenr(h))
-               ++fail;
+               sblock->header_error = 1;
 
-       if (sblock->pagev[0]->generation != btrfs_stack_header_generation(h))
-               ++fail;
+       if (sblock->pagev[0]->generation != btrfs_stack_header_generation(h)) {
+               sblock->header_error = 1;
+               sblock->generation_error = 1;
+       }
 
        if (!scrub_check_fsid(h->fsid, sblock->pagev[0]))
-               ++fail;
+               sblock->header_error = 1;
 
        if (memcmp(h->chunk_tree_uuid, fs_info->chunk_tree_uuid,
                   BTRFS_UUID_SIZE))
-               ++fail;
+               sblock->header_error = 1;
 
        len = sctx->nodesize - BTRFS_CSUM_SIZE;
        mapped_size = PAGE_SIZE - BTRFS_CSUM_SIZE;
@@ -1960,9 +1918,9 @@ static int scrub_checksum_tree_block(struct scrub_block *sblock)
 
        btrfs_csum_final(crc, calculated_csum);
        if (memcmp(calculated_csum, on_disk_csum, sctx->csum_size))
-               ++crc_fail;
+               sblock->checksum_error = 1;
 
-       return fail || crc_fail;
+       return sblock->header_error || sblock->checksum_error;
 }
 
 static int scrub_checksum_super(struct scrub_block *sblock)
@@ -2176,39 +2134,27 @@ static void scrub_missing_raid56_worker(struct btrfs_work *work)
 {
        struct scrub_block *sblock = container_of(work, struct scrub_block, work);
        struct scrub_ctx *sctx = sblock->sctx;
-       struct btrfs_fs_info *fs_info = sctx->dev_root->fs_info;
-       unsigned int is_metadata;
-       unsigned int have_csum;
-       u8 *csum;
-       u64 generation;
        u64 logical;
        struct btrfs_device *dev;
 
-       is_metadata = !(sblock->pagev[0]->flags & BTRFS_EXTENT_FLAG_DATA);
-       have_csum = sblock->pagev[0]->have_csum;
-       csum = sblock->pagev[0]->csum;
-       generation = sblock->pagev[0]->generation;
        logical = sblock->pagev[0]->logical;
        dev = sblock->pagev[0]->dev;
 
-       if (sblock->no_io_error_seen) {
-               scrub_recheck_block_checksum(fs_info, sblock, is_metadata,
-                                            have_csum, csum, generation,
-                                            sctx->csum_size);
-       }
+       if (sblock->no_io_error_seen)
+               scrub_recheck_block_checksum(sblock);
 
        if (!sblock->no_io_error_seen) {
                spin_lock(&sctx->stat_lock);
                sctx->stat.read_errors++;
                spin_unlock(&sctx->stat_lock);
-               btrfs_err_rl_in_rcu(fs_info,
+               btrfs_err_rl_in_rcu(sctx->dev_root->fs_info,
                        "IO error rebuilding logical %llu for dev %s",
                        logical, rcu_str_deref(dev->name));
        } else if (sblock->header_error || sblock->checksum_error) {
                spin_lock(&sctx->stat_lock);
                sctx->stat.uncorrectable_errors++;
                spin_unlock(&sctx->stat_lock);
-               btrfs_err_rl_in_rcu(fs_info,
+               btrfs_err_rl_in_rcu(sctx->dev_root->fs_info,
                        "failed to rebuild valid logical %llu for dev %s",
                        logical, rcu_str_deref(dev->name));
        } else {
@@ -2500,8 +2446,7 @@ static void scrub_block_complete(struct scrub_block *sblock)
        }
 }
 
-static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u64 len,
-                          u8 *csum)
+static int scrub_find_csum(struct scrub_ctx *sctx, u64 logical, u8 *csum)
 {
        struct btrfs_ordered_sum *sum = NULL;
        unsigned long index;
@@ -2565,7 +2510,7 @@ static int scrub_extent(struct scrub_ctx *sctx, u64 logical, u64 len,
 
                if (flags & BTRFS_EXTENT_FLAG_DATA) {
                        /* push csums to sbio */
-                       have_csum = scrub_find_csum(sctx, logical, l, csum);
+                       have_csum = scrub_find_csum(sctx, logical, csum);
                        if (have_csum == 0)
                                ++sctx->stat.no_csum;
                        if (sctx->is_dev_replace && !have_csum) {
@@ -2703,7 +2648,7 @@ static int scrub_extent_for_parity(struct scrub_parity *sparity,
 
                if (flags & BTRFS_EXTENT_FLAG_DATA) {
                        /* push csums to sbio */
-                       have_csum = scrub_find_csum(sctx, logical, l, csum);
+                       have_csum = scrub_find_csum(sctx, logical, csum);
                        if (have_csum == 0)
                                goto skip;
                }
@@ -3012,6 +2957,9 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
                             logic_start + map->stripe_len)) {
                                btrfs_err(fs_info, "scrub: tree block %llu spanning stripes, ignored. logical=%llu",
                                          key.objectid, logic_start);
+                               spin_lock(&sctx->stat_lock);
+                               sctx->stat.uncorrectable_errors++;
+                               spin_unlock(&sctx->stat_lock);
                                goto next;
                        }
 again:
@@ -3361,6 +3309,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
                                           "scrub: tree block %llu spanning "
                                           "stripes, ignored. logical=%llu",
                                       key.objectid, logical);
+                               spin_lock(&sctx->stat_lock);
+                               sctx->stat.uncorrectable_errors++;
+                               spin_unlock(&sctx->stat_lock);
                                goto next;
                        }
 
@@ -3481,7 +3432,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
                                          struct btrfs_device *scrub_dev,
                                          u64 chunk_offset, u64 length,
-                                         u64 dev_offset, int is_dev_replace)
+                                         u64 dev_offset,
+                                         struct btrfs_block_group_cache *cache,
+                                         int is_dev_replace)
 {
        struct btrfs_mapping_tree *map_tree =
                &sctx->dev_root->fs_info->mapping_tree;
@@ -3494,8 +3447,18 @@ static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
        em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1);
        read_unlock(&map_tree->map_tree.lock);
 
-       if (!em)
-               return -EINVAL;
+       if (!em) {
+               /*
+                * Might have been an unused block group deleted by the cleaner
+                * kthread or relocation.
+                */
+               spin_lock(&cache->lock);
+               if (!cache->removed)
+                       ret = -EINVAL;
+               spin_unlock(&cache->lock);
+
+               return ret;
+       }
 
        map = (struct map_lookup *)em->bdev;
        if (em->start != chunk_offset)
@@ -3532,6 +3495,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
        u64 length;
        u64 chunk_offset;
        int ret = 0;
+       int ro_set;
        int slot;
        struct extent_buffer *l;
        struct btrfs_key key;
@@ -3617,7 +3581,21 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                scrub_pause_on(fs_info);
                ret = btrfs_inc_block_group_ro(root, cache);
                scrub_pause_off(fs_info);
-               if (ret) {
+
+               if (ret == 0) {
+                       ro_set = 1;
+               } else if (ret == -ENOSPC) {
+                       /*
+                        * btrfs_inc_block_group_ro return -ENOSPC when it
+                        * failed in creating new chunk for metadata.
+                        * It is not a problem for scrub/replace, because
+                        * metadata are always cowed, and our scrub paused
+                        * commit_transactions.
+                        */
+                       ro_set = 0;
+               } else {
+                       btrfs_warn(fs_info, "failed setting block group ro, ret=%d\n",
+                                  ret);
                        btrfs_put_block_group(cache);
                        break;
                }
@@ -3626,7 +3604,7 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                dev_replace->cursor_left = found_key.offset;
                dev_replace->item_needs_writeback = 1;
                ret = scrub_chunk(sctx, scrub_dev, chunk_offset, length,
-                                 found_key.offset, is_dev_replace);
+                                 found_key.offset, cache, is_dev_replace);
 
                /*
                 * flush, submit all pending read and write bios, afterwards
@@ -3660,7 +3638,30 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 
                scrub_pause_off(fs_info);
 
-               btrfs_dec_block_group_ro(root, cache);
+               if (ro_set)
+                       btrfs_dec_block_group_ro(root, cache);
+
+               /*
+                * We might have prevented the cleaner kthread from deleting
+                * this block group if it was already unused because we raced
+                * and set it to RO mode first. So add it back to the unused
+                * list, otherwise it might not ever be deleted unless a manual
+                * balance is triggered or it becomes used and unused again.
+                */
+               spin_lock(&cache->lock);
+               if (!cache->removed && !cache->ro && cache->reserved == 0 &&
+                   btrfs_block_group_used(&cache->item) == 0) {
+                       spin_unlock(&cache->lock);
+                       spin_lock(&fs_info->unused_bgs_lock);
+                       if (list_empty(&cache->bg_list)) {
+                               btrfs_get_block_group(cache);
+                               list_add_tail(&cache->bg_list,
+                                             &fs_info->unused_bgs);
+                       }
+                       spin_unlock(&fs_info->unused_bgs_lock);
+               } else {
+                       spin_unlock(&cache->lock);
+               }
 
                btrfs_put_block_group(cache);
                if (ret)
index c8c3d70c31ffad4e02acd04e0f7dcaa54ad0fe2b..8b72b005bfb9a212518a711a2e476c2d70b47b24 100644 (file)
@@ -898,8 +898,10 @@ int btrfs_test_free_space_cache(void)
        }
 
        root = btrfs_alloc_dummy_root();
-       if (!root)
+       if (IS_ERR(root)) {
+               ret = PTR_ERR(root);
                goto out;
+       }
 
        root->fs_info = btrfs_alloc_dummy_fs_info();
        if (!root->fs_info)
index 418c6a2ad7d88658f8624d99a1ba0e9e84c13d45..3367a3c6f214f5ca248a79fff36c6404a49fbf4f 100644 (file)
@@ -592,6 +592,38 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
        return start_transaction(root, num_items, TRANS_START,
                                 BTRFS_RESERVE_FLUSH_ALL);
 }
+struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
+                                       struct btrfs_root *root,
+                                       unsigned int num_items,
+                                       int min_factor)
+{
+       struct btrfs_trans_handle *trans;
+       u64 num_bytes;
+       int ret;
+
+       trans = btrfs_start_transaction(root, num_items);
+       if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
+               return trans;
+
+       trans = btrfs_start_transaction(root, 0);
+       if (IS_ERR(trans))
+               return trans;
+
+       num_bytes = btrfs_calc_trans_metadata_size(root, num_items);
+       ret = btrfs_cond_migrate_bytes(root->fs_info,
+                                      &root->fs_info->trans_block_rsv,
+                                      num_bytes,
+                                      min_factor);
+       if (ret) {
+               btrfs_end_transaction(trans, root);
+               return ERR_PTR(ret);
+       }
+
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
+       trans->bytes_reserved = num_bytes;
+
+       return trans;
+}
 
 struct btrfs_trans_handle *btrfs_start_transaction_lflush(
                                        struct btrfs_root *root,
index b05b2f64d9133313f1af231c4a4254ff16972f00..0da21ca9b3fb312a7ec77b4e8314a9e4b3410075 100644 (file)
@@ -185,6 +185,10 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root);
 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
                                                   unsigned int num_items);
+struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
+                                       struct btrfs_root *root,
+                                       unsigned int num_items,
+                                       int min_factor);
 struct btrfs_trans_handle *btrfs_start_transaction_lflush(
                                        struct btrfs_root *root,
                                        unsigned int num_items);
index 9b2dafa5ba59178644c6c01879583cc2769a52e8..45645220660996773b1f76cd1d526d4aeae33dac 100644 (file)
@@ -1973,8 +1973,7 @@ void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_fs_info *fs_info,
        if (srcdev->writeable) {
                fs_devices->rw_devices--;
                /* zero out the old super if it is writable */
-               btrfs_scratch_superblocks(srcdev->bdev,
-                                       rcu_str_deref(srcdev->name));
+               btrfs_scratch_superblocks(srcdev->bdev, srcdev->name->str);
        }
 
        if (srcdev->bdev)
@@ -2024,8 +2023,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
        btrfs_sysfs_rm_device_link(fs_info->fs_devices, tgtdev);
 
        if (tgtdev->bdev) {
-               btrfs_scratch_superblocks(tgtdev->bdev,
-                                       rcu_str_deref(tgtdev->name));
+               btrfs_scratch_superblocks(tgtdev->bdev, tgtdev->name->str);
                fs_info->fs_devices->open_devices--;
        }
        fs_info->fs_devices->num_devices--;
@@ -2853,7 +2851,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset)
        if (ret)
                return ret;
 
-       trans = btrfs_start_transaction(root, 0);
+       trans = btrfs_start_trans_remove_block_group(root->fs_info,
+                                                    chunk_offset);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
                btrfs_std_error(root->fs_info, ret, NULL);
@@ -3123,7 +3122,7 @@ static int chunk_profiles_filter(u64 chunk_type,
        return 1;
 }
 
-static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
+static int chunk_usage_range_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
                              struct btrfs_balance_args *bargs)
 {
        struct btrfs_block_group_cache *cache;
@@ -3156,7 +3155,7 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
        return ret;
 }
 
-static int chunk_usage_range_filter(struct btrfs_fs_info *fs_info,
+static int chunk_usage_filter(struct btrfs_fs_info *fs_info,
                u64 chunk_offset, struct btrfs_balance_args *bargs)
 {
        struct btrfs_block_group_cache *cache;
@@ -3400,6 +3399,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
        u32 count_data = 0;
        u32 count_meta = 0;
        u32 count_sys = 0;
+       int chunk_reserved = 0;
 
        /* step one make some room on all the devices */
        devices = &fs_info->fs_devices->devices;
@@ -3501,6 +3501,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
 
                ret = should_balance_chunk(chunk_root, leaf, chunk,
                                           found_key.offset);
+
                btrfs_release_path(path);
                if (!ret) {
                        mutex_unlock(&fs_info->delete_unused_bgs_mutex);
@@ -3537,6 +3538,25 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
                        goto loop;
                }
 
+               if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && !chunk_reserved) {
+                       trans = btrfs_start_transaction(chunk_root, 0);
+                       if (IS_ERR(trans)) {
+                               mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+                               ret = PTR_ERR(trans);
+                               goto error;
+                       }
+
+                       ret = btrfs_force_chunk_alloc(trans, chunk_root,
+                                                     BTRFS_BLOCK_GROUP_DATA);
+                       if (ret < 0) {
+                               mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+                               goto error;
+                       }
+
+                       btrfs_end_transaction(trans, chunk_root);
+                       chunk_reserved = 1;
+               }
+
                ret = btrfs_relocate_chunk(chunk_root,
                                           found_key.offset);
                mutex_unlock(&fs_info->delete_unused_bgs_mutex);
index ec571237273208fcb87f7be1c473b0c6a1392b50..d5c84f6b13538a338d90560b6520be4fe56c3125 100644 (file)
@@ -382,7 +382,7 @@ struct map_lookup {
 #define BTRFS_BALANCE_ARGS_LIMIT       (1ULL << 5)
 #define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6)
 #define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7)
-#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 8)
+#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10)
 
 #define BTRFS_BALANCE_ARGS_MASK                        \
        (BTRFS_BALANCE_ARGS_PROFILES |          \
index 6f518c90e1c14b6966d80ab9202c0bff0e399686..1fcd7b6e7564defa675b3abe12589473a58e937d 100644 (file)
@@ -313,8 +313,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                /* check to make sure this item is what we want */
                if (found_key.objectid != key.objectid)
                        break;
-               if (found_key.type != BTRFS_XATTR_ITEM_KEY)
+               if (found_key.type > BTRFS_XATTR_ITEM_KEY)
                        break;
+               if (found_key.type < BTRFS_XATTR_ITEM_KEY)
+                       goto next;
 
                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
                if (verify_dir_item(root, leaf, di))
index 7a6b02f727874352d80a9fd34fa0355dda8a5cb1..c0f3da3926a0c6d4b8cf95e2c24a2a1ebd9d6655 100644 (file)
@@ -879,7 +879,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        loff_t pos, eof;
        size_t len;
        void *data;
-       int ret;
+       int ret = -ENOBUFS;
 
        ASSERT(op != NULL);
        ASSERT(page != NULL);
index 834f9f3723fbe3980e8a9705e8c1d0f86936eb40..a4766ded1ba78e8bbbff70d4c5e65b3f9060d687 100644 (file)
@@ -88,7 +88,7 @@ static uint16_t ceph_fscache_inode_get_key(const void *cookie_netfs_data,
        const struct ceph_inode_info* ci = cookie_netfs_data;
        uint16_t klen;
 
-       /* use ceph virtual inode (id + snaphot) */
+       /* use ceph virtual inode (id + snapshot) */
        klen = sizeof(ci->i_vino);
        if (klen > maxbuf)
                return 0;
index 27b566874bc1d2b0494b49ebe1769f380ccf8648..c69e1253b47bfbefb2eb2cb1564a5c4b9d87f9a3 100644 (file)
@@ -1655,9 +1655,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,
            !S_ISDIR(inode->i_mode) &&          /* ignore readdir cache */
            ci->i_wrbuffer_ref == 0 &&          /* no dirty pages... */
            inode->i_data.nrpages &&            /* have cached pages */
-           (file_wanted == 0 ||                /* no open files */
-            (revoking & (CEPH_CAP_FILE_CACHE|
-                         CEPH_CAP_FILE_LAZYIO))) && /*  or revoking cache */
+           (revoking & (CEPH_CAP_FILE_CACHE|
+                        CEPH_CAP_FILE_LAZYIO)) && /*  or revoking cache */
            !tried_invalidate) {
                dout("check_caps trying to invalidate on %p\n", inode);
                if (try_nonblocking_invalidate(inode) < 0) {
@@ -1971,49 +1970,46 @@ static void sync_write_wait(struct inode *inode)
 }
 
 /*
- * wait for any uncommitted directory operations to commit.
+ * wait for any unsafe requests to complete.
  */
-static int unsafe_dirop_wait(struct inode *inode)
+static int unsafe_request_wait(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct list_head *head = &ci->i_unsafe_dirops;
-       struct ceph_mds_request *req;
-       u64 last_tid;
-       int ret = 0;
-
-       if (!S_ISDIR(inode->i_mode))
-               return 0;
+       struct ceph_mds_request *req1 = NULL, *req2 = NULL;
+       int ret, err = 0;
 
        spin_lock(&ci->i_unsafe_lock);
-       if (list_empty(head))
-               goto out;
-
-       req = list_last_entry(head, struct ceph_mds_request,
-                             r_unsafe_dir_item);
-       last_tid = req->r_tid;
-
-       do {
-               ceph_mdsc_get_request(req);
-               spin_unlock(&ci->i_unsafe_lock);
+       if (S_ISDIR(inode->i_mode) && !list_empty(&ci->i_unsafe_dirops)) {
+               req1 = list_last_entry(&ci->i_unsafe_dirops,
+                                       struct ceph_mds_request,
+                                       r_unsafe_dir_item);
+               ceph_mdsc_get_request(req1);
+       }
+       if (!list_empty(&ci->i_unsafe_iops)) {
+               req2 = list_last_entry(&ci->i_unsafe_iops,
+                                       struct ceph_mds_request,
+                                       r_unsafe_target_item);
+               ceph_mdsc_get_request(req2);
+       }
+       spin_unlock(&ci->i_unsafe_lock);
 
-               dout("unsafe_dirop_wait %p wait on tid %llu (until %llu)\n",
-                    inode, req->r_tid, last_tid);
-               ret = !wait_for_completion_timeout(&req->r_safe_completion,
-                                       ceph_timeout_jiffies(req->r_timeout));
+       dout("unsafe_requeset_wait %p wait on tid %llu %llu\n",
+            inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL);
+       if (req1) {
+               ret = !wait_for_completion_timeout(&req1->r_safe_completion,
+                                       ceph_timeout_jiffies(req1->r_timeout));
                if (ret)
-                       ret = -EIO;  /* timed out */
-
-               ceph_mdsc_put_request(req);
-
-               spin_lock(&ci->i_unsafe_lock);
-               if (ret || list_empty(head))
-                       break;
-               req = list_first_entry(head, struct ceph_mds_request,
-                                      r_unsafe_dir_item);
-       } while (req->r_tid < last_tid);
-out:
-       spin_unlock(&ci->i_unsafe_lock);
-       return ret;
+                       err = -EIO;
+               ceph_mdsc_put_request(req1);
+       }
+       if (req2) {
+               ret = !wait_for_completion_timeout(&req2->r_safe_completion,
+                                       ceph_timeout_jiffies(req2->r_timeout));
+               if (ret)
+                       err = -EIO;
+               ceph_mdsc_put_request(req2);
+       }
+       return err;
 }
 
 int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
@@ -2039,7 +2035,7 @@ int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        dirty = try_flush_caps(inode, &flush_tid);
        dout("fsync dirty caps are %s\n", ceph_cap_string(dirty));
 
-       ret = unsafe_dirop_wait(inode);
+       ret = unsafe_request_wait(inode);
 
        /*
         * only wait on non-file metadata writeback (the mds
index 0c62868b5c561b37fa866b68bbe34f3ffb1fd6a6..3c68e6aee2f0531bdd8afb0125bbae48419d0dfb 100644 (file)
  * need to wait for MDS acknowledgement.
  */
 
+/*
+ * Calculate the length sum of direct io vectors that can
+ * be combined into one page vector.
+ */
+static size_t dio_get_pagev_size(const struct iov_iter *it)
+{
+    const struct iovec *iov = it->iov;
+    const struct iovec *iovend = iov + it->nr_segs;
+    size_t size;
+
+    size = iov->iov_len - it->iov_offset;
+    /*
+     * An iov can be page vectored when both the current tail
+     * and the next base are page aligned.
+     */
+    while (PAGE_ALIGNED((iov->iov_base + iov->iov_len)) &&
+           (++iov < iovend && PAGE_ALIGNED((iov->iov_base)))) {
+        size += iov->iov_len;
+    }
+    dout("dio_get_pagevlen len = %zu\n", size);
+    return size;
+}
+
+/*
+ * Allocate a page vector based on (@it, @nbytes).
+ * The return value is the tuple describing a page vector,
+ * that is (@pages, @page_align, @num_pages).
+ */
+static struct page **
+dio_get_pages_alloc(const struct iov_iter *it, size_t nbytes,
+                   size_t *page_align, int *num_pages)
+{
+       struct iov_iter tmp_it = *it;
+       size_t align;
+       struct page **pages;
+       int ret = 0, idx, npages;
+
+       align = (unsigned long)(it->iov->iov_base + it->iov_offset) &
+               (PAGE_SIZE - 1);
+       npages = calc_pages_for(align, nbytes);
+       pages = kmalloc(sizeof(*pages) * npages, GFP_KERNEL);
+       if (!pages) {
+               pages = vmalloc(sizeof(*pages) * npages);
+               if (!pages)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       for (idx = 0; idx < npages; ) {
+               size_t start;
+               ret = iov_iter_get_pages(&tmp_it, pages + idx, nbytes,
+                                        npages - idx, &start);
+               if (ret < 0)
+                       goto fail;
+
+               iov_iter_advance(&tmp_it, ret);
+               nbytes -= ret;
+               idx += (ret + start + PAGE_SIZE - 1) / PAGE_SIZE;
+       }
+
+       BUG_ON(nbytes != 0);
+       *num_pages = npages;
+       *page_align = align;
+       dout("dio_get_pages_alloc: got %d pages align %zu\n", npages, align);
+       return pages;
+fail:
+       ceph_put_page_vector(pages, idx, false);
+       return ERR_PTR(ret);
+}
 
 /*
  * Prepare an open request.  Preallocate ceph_cap to avoid an
@@ -458,11 +526,10 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
                        size_t start;
                        ssize_t n;
 
-                       n = iov_iter_get_pages_alloc(i, &pages, INT_MAX, &start);
-                       if (n < 0)
-                               return n;
-
-                       num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;
+                       n = dio_get_pagev_size(i);
+                       pages = dio_get_pages_alloc(i, n, &start, &num_pages);
+                       if (IS_ERR(pages))
+                               return PTR_ERR(pages);
 
                        ret = striped_read(inode, off, n,
                                           pages, num_pages, checkeof,
@@ -592,7 +659,7 @@ ceph_sync_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
                CEPH_OSD_FLAG_WRITE;
 
        while (iov_iter_count(from) > 0) {
-               u64 len = iov_iter_single_seg_count(from);
+               u64 len = dio_get_pagev_size(from);
                size_t start;
                ssize_t n;
 
@@ -611,14 +678,14 @@ ceph_sync_direct_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
 
                osd_req_op_init(req, 1, CEPH_OSD_OP_STARTSYNC, 0);
 
-               n = iov_iter_get_pages_alloc(from, &pages, len, &start);
-               if (unlikely(n < 0)) {
-                       ret = n;
+               n = len;
+               pages = dio_get_pages_alloc(from, len, &start, &num_pages);
+               if (IS_ERR(pages)) {
                        ceph_osdc_put_request(req);
+                       ret = PTR_ERR(pages);
                        break;
                }
 
-               num_pages = (n + start + PAGE_SIZE - 1) / PAGE_SIZE;
                /*
                 * throw out any page cache pages in this range. this
                 * may block.
index 96d2bd8299022e554c8bfdc0b7f1c759be8fc8cd..498dcfa2dcdbedf393ae26fc9f7f68cf90bceb90 100644 (file)
@@ -452,6 +452,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
 
        INIT_LIST_HEAD(&ci->i_unsafe_writes);
        INIT_LIST_HEAD(&ci->i_unsafe_dirops);
+       INIT_LIST_HEAD(&ci->i_unsafe_iops);
        spin_lock_init(&ci->i_unsafe_lock);
 
        ci->i_snap_realm = NULL;
index 51cb02da75d98979b18e05d7bdad4dee89e258d4..e7b130a637f9f31a34efd67d6cf5789a8fcdef00 100644 (file)
@@ -633,13 +633,8 @@ static void __register_request(struct ceph_mds_client *mdsc,
                mdsc->oldest_tid = req->r_tid;
 
        if (dir) {
-               struct ceph_inode_info *ci = ceph_inode(dir);
-
                ihold(dir);
-               spin_lock(&ci->i_unsafe_lock);
                req->r_unsafe_dir = dir;
-               list_add_tail(&req->r_unsafe_dir_item, &ci->i_unsafe_dirops);
-               spin_unlock(&ci->i_unsafe_lock);
        }
 }
 
@@ -665,13 +660,20 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
        rb_erase(&req->r_node, &mdsc->request_tree);
        RB_CLEAR_NODE(&req->r_node);
 
-       if (req->r_unsafe_dir) {
+       if (req->r_unsafe_dir && req->r_got_unsafe) {
                struct ceph_inode_info *ci = ceph_inode(req->r_unsafe_dir);
-
                spin_lock(&ci->i_unsafe_lock);
                list_del_init(&req->r_unsafe_dir_item);
                spin_unlock(&ci->i_unsafe_lock);
+       }
+       if (req->r_target_inode && req->r_got_unsafe) {
+               struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
+               spin_lock(&ci->i_unsafe_lock);
+               list_del_init(&req->r_unsafe_target_item);
+               spin_unlock(&ci->i_unsafe_lock);
+       }
 
+       if (req->r_unsafe_dir) {
                iput(req->r_unsafe_dir);
                req->r_unsafe_dir = NULL;
        }
@@ -1430,6 +1432,13 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
                if ((used | wanted) & CEPH_CAP_ANY_WR)
                        goto out;
        }
+       /* The inode has cached pages, but it's no longer used.
+        * we can safely drop it */
+       if (wanted == 0 && used == CEPH_CAP_FILE_CACHE &&
+           !(oissued & CEPH_CAP_FILE_CACHE)) {
+         used = 0;
+         oissued = 0;
+       }
        if ((used | wanted) & ~oissued & mine)
                goto out;   /* we need these caps */
 
@@ -1438,7 +1447,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
                /* we aren't the only cap.. just remove us */
                __ceph_remove_cap(cap, true);
        } else {
-               /* try to drop referring dentries */
+               /* try dropping referring dentries */
                spin_unlock(&ci->i_ceph_lock);
                d_prune_aliases(inode);
                dout("trim_caps_cb %p cap %p  pruned, count now %d\n",
@@ -1704,6 +1713,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
        req->r_started = jiffies;
        req->r_resend_mds = -1;
        INIT_LIST_HEAD(&req->r_unsafe_dir_item);
+       INIT_LIST_HEAD(&req->r_unsafe_target_item);
        req->r_fmode = -1;
        kref_init(&req->r_kref);
        INIT_LIST_HEAD(&req->r_wait);
@@ -1935,7 +1945,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
        len = sizeof(*head) +
                pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) +
-               sizeof(struct timespec);
+               sizeof(struct ceph_timespec);
 
        /* calculate (max) length for cap releases */
        len += sizeof(struct ceph_mds_request_release) *
@@ -2477,6 +2487,14 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        } else {
                req->r_got_unsafe = true;
                list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe);
+               if (req->r_unsafe_dir) {
+                       struct ceph_inode_info *ci =
+                                       ceph_inode(req->r_unsafe_dir);
+                       spin_lock(&ci->i_unsafe_lock);
+                       list_add_tail(&req->r_unsafe_dir_item,
+                                     &ci->i_unsafe_dirops);
+                       spin_unlock(&ci->i_unsafe_lock);
+               }
        }
 
        dout("handle_reply tid %lld result %d\n", tid, result);
@@ -2518,6 +2536,13 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
        up_read(&mdsc->snap_rwsem);
        if (realm)
                ceph_put_snap_realm(mdsc, realm);
+
+       if (err == 0 && req->r_got_unsafe && req->r_target_inode) {
+               struct ceph_inode_info *ci = ceph_inode(req->r_target_inode);
+               spin_lock(&ci->i_unsafe_lock);
+               list_add_tail(&req->r_unsafe_target_item, &ci->i_unsafe_iops);
+               spin_unlock(&ci->i_unsafe_lock);
+       }
 out_err:
        mutex_lock(&mdsc->mutex);
        if (!req->r_aborted) {
@@ -3917,17 +3942,19 @@ static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con,
        return msg;
 }
 
-static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
+static int mds_sign_message(struct ceph_msg *msg)
 {
-       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_session *s = msg->con->private;
        struct ceph_auth_handshake *auth = &s->s_auth;
+
        return ceph_auth_sign_message(auth, msg);
 }
 
-static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
+static int mds_check_message_signature(struct ceph_msg *msg)
 {
-       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_session *s = msg->con->private;
        struct ceph_auth_handshake *auth = &s->s_auth;
+
        return ceph_auth_check_message_signature(auth, msg);
 }
 
@@ -3940,8 +3967,8 @@ static const struct ceph_connection_operations mds_con_ops = {
        .invalidate_authorizer = invalidate_authorizer,
        .peer_reset = peer_reset,
        .alloc_msg = mds_alloc_msg,
-       .sign_message = sign_message,
-       .check_message_signature = check_message_signature,
+       .sign_message = mds_sign_message,
+       .check_message_signature = mds_check_message_signature,
 };
 
 /* eof */
index f575eafe2261cbd5974d8d4f072879e9d5bd7a39..ccf11ef0ca8717f79e6bfc9d6cf806ec359b5e8c 100644 (file)
@@ -236,6 +236,9 @@ struct ceph_mds_request {
        struct inode    *r_unsafe_dir;
        struct list_head r_unsafe_dir_item;
 
+       /* unsafe requests that modify the target inode */
+       struct list_head r_unsafe_target_item;
+
        struct ceph_mds_session *r_session;
 
        int               r_attempts;   /* resend attempts */
index 2f2460d23a0600f8f9bf2e1cc4fe3b2286684356..75b7d125ce668a9b3f4f851d2be1c688d6d5f964 100644 (file)
@@ -342,6 +342,7 @@ struct ceph_inode_info {
 
        struct list_head i_unsafe_writes; /* uncommitted sync writes */
        struct list_head i_unsafe_dirops; /* uncommitted mds dir ops */
+       struct list_head i_unsafe_iops;   /* uncommitted mds inode ops */
        spinlock_t i_unsafe_lock;
 
        struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */
index e739950ca08485543db80bee53f1021384ed0b9a..cbc0f4bca0c0dfa73b6a545fb6978a72b1a702ef 100644 (file)
@@ -454,6 +454,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
                seq_puts(s, ",nocase");
        if (tcon->retry)
                seq_puts(s, ",hard");
+       if (tcon->use_persistent)
+               seq_puts(s, ",persistenthandles");
+       else if (tcon->use_resilient)
+               seq_puts(s, ",resilienthandles");
        if (tcon->unix_ext)
                seq_puts(s, ",unix");
        else
@@ -921,9 +925,7 @@ const struct file_operations cifs_file_ops = {
        .mmap  = cifs_file_mmap,
        .splice_read = generic_file_splice_read,
        .llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
@@ -939,9 +941,7 @@ const struct file_operations cifs_file_strict_ops = {
        .mmap = cifs_file_strict_mmap,
        .splice_read = generic_file_splice_read,
        .llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
@@ -957,9 +957,7 @@ const struct file_operations cifs_file_direct_ops = {
        .flush = cifs_flush,
        .mmap = cifs_file_mmap,
        .splice_read = generic_file_splice_read,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl  = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .llseek = cifs_llseek,
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
@@ -975,9 +973,7 @@ const struct file_operations cifs_file_nobrl_ops = {
        .mmap  = cifs_file_mmap,
        .splice_read = generic_file_splice_read,
        .llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
@@ -992,9 +988,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
        .mmap = cifs_file_strict_mmap,
        .splice_read = generic_file_splice_read,
        .llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
@@ -1009,9 +1003,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
        .flush = cifs_flush,
        .mmap = cifs_file_mmap,
        .splice_read = generic_file_splice_read,
-#ifdef CONFIG_CIFS_POSIX
        .unlocked_ioctl  = cifs_ioctl,
-#endif /* CONFIG_CIFS_POSIX */
        .llseek = cifs_llseek,
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
index b406a32deb1f6bf2f9e8d416bc019a71f589d8db..2b510c537a0d588c532fe9200cdd4a9b03a4c9f4 100644 (file)
@@ -493,7 +493,10 @@ struct smb_vol {
        bool mfsymlinks:1; /* use Minshall+French Symlinks */
        bool multiuser:1;
        bool rwpidforward:1; /* pid forward for read/write operations */
-       bool nosharesock;
+       bool nosharesock:1;
+       bool persistent:1;
+       bool nopersistent:1;
+       bool resilient:1; /* noresilient not required since not fored for CA */
        unsigned int rsize;
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
@@ -895,6 +898,8 @@ struct cifs_tcon {
        bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
        bool broken_sparse_sup; /* if server or share does not support sparse */
        bool need_reconnect:1; /* connection reset, tid now invalid */
+       bool use_resilient:1; /* use resilient instead of durable handles */
+       bool use_persistent:1; /* use persistent instead of durable handles */
 #ifdef CONFIG_CIFS_SMB2
        bool print:1;           /* set if connection to printer share */
        bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
@@ -1015,6 +1020,7 @@ struct cifs_fid {
        __u64 persistent_fid;   /* persist file id for smb2 */
        __u64 volatile_fid;     /* volatile file id for smb2 */
        __u8 lease_key[SMB2_LEASE_KEY_SIZE];    /* lease key for smb2 */
+       __u8 create_guid[16];
 #endif
        struct cifs_pending_open *pending_open;
        unsigned int epoch;
index 3f2228570d441840b7e6d11c10a3b814a2b60962..ecb0803bdb0e50479f50b0e874a4e87cb064e2d0 100644 (file)
@@ -87,6 +87,8 @@ enum {
        Opt_sign, Opt_seal, Opt_noac,
        Opt_fsc, Opt_mfsymlinks,
        Opt_multiuser, Opt_sloppy, Opt_nosharesock,
+       Opt_persistent, Opt_nopersistent,
+       Opt_resilient, Opt_noresilient,
 
        /* Mount options which take numeric value */
        Opt_backupuid, Opt_backupgid, Opt_uid,
@@ -169,6 +171,10 @@ static const match_table_t cifs_mount_option_tokens = {
        { Opt_multiuser, "multiuser" },
        { Opt_sloppy, "sloppy" },
        { Opt_nosharesock, "nosharesock" },
+       { Opt_persistent, "persistenthandles"},
+       { Opt_nopersistent, "nopersistenthandles"},
+       { Opt_resilient, "resilienthandles"},
+       { Opt_noresilient, "noresilienthandles"},
 
        { Opt_backupuid, "backupuid=%s" },
        { Opt_backupgid, "backupgid=%s" },
@@ -1497,6 +1503,33 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                case Opt_nosharesock:
                        vol->nosharesock = true;
                        break;
+               case Opt_nopersistent:
+                       vol->nopersistent = true;
+                       if (vol->persistent) {
+                               cifs_dbg(VFS,
+                                 "persistenthandles mount options conflict\n");
+                               goto cifs_parse_mount_err;
+                       }
+                       break;
+               case Opt_persistent:
+                       vol->persistent = true;
+                       if ((vol->nopersistent) || (vol->resilient)) {
+                               cifs_dbg(VFS,
+                                 "persistenthandles mount options conflict\n");
+                               goto cifs_parse_mount_err;
+                       }
+                       break;
+               case Opt_resilient:
+                       vol->resilient = true;
+                       if (vol->persistent) {
+                               cifs_dbg(VFS,
+                                 "persistenthandles mount options conflict\n");
+                               goto cifs_parse_mount_err;
+                       }
+                       break;
+               case Opt_noresilient:
+                       vol->resilient = false; /* already the default */
+                       break;
 
                /* Numeric Values */
                case Opt_backupuid:
@@ -2655,6 +2688,42 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
                cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
        }
        tcon->seal = volume_info->seal;
+       tcon->use_persistent = false;
+       /* check if SMB2 or later, CIFS does not support persistent handles */
+       if (volume_info->persistent) {
+               if (ses->server->vals->protocol_id == 0) {
+                       cifs_dbg(VFS,
+                            "SMB3 or later required for persistent handles\n");
+                       rc = -EOPNOTSUPP;
+                       goto out_fail;
+#ifdef CONFIG_CIFS_SMB2
+               } else if (ses->server->capabilities &
+                          SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
+                       tcon->use_persistent = true;
+               else /* persistent handles requested but not supported */ {
+                       cifs_dbg(VFS,
+                               "Persistent handles not supported on share\n");
+                       rc = -EOPNOTSUPP;
+                       goto out_fail;
+#endif /* CONFIG_CIFS_SMB2 */
+               }
+#ifdef CONFIG_CIFS_SMB2
+       } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
+            && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
+            && (volume_info->nopersistent == false)) {
+               cifs_dbg(FYI, "enabling persistent handles\n");
+               tcon->use_persistent = true;
+#endif /* CONFIG_CIFS_SMB2 */
+       } else if (volume_info->resilient) {
+               if (ses->server->vals->protocol_id == 0) {
+                       cifs_dbg(VFS,
+                            "SMB2.1 or later required for resilient handles\n");
+                       rc = -EOPNOTSUPP;
+                       goto out_fail;
+               }
+               tcon->use_resilient = true;
+       }
+
        /*
         * We can have only one retry value for a connection to a share so for
         * resources mounted more than once to the same server share the last
@@ -3503,6 +3572,15 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
                goto mount_fail_check;
        }
 
+#ifdef CONFIG_CIFS_SMB2
+       if ((volume_info->persistent == true) && ((ses->server->capabilities &
+               SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
+               cifs_dbg(VFS, "persistent handles not supported by server\n");
+               rc = -EOPNOTSUPP;
+               goto mount_fail_check;
+       }
+#endif /* CONFIG_CIFS_SMB2*/
+
        /* search for existing tcon to this server share */
        tcon = cifs_get_tcon(ses, volume_info);
        if (IS_ERR(tcon)) {
index 28a77bf1d55924693d27d1c701571e1b1fef2d49..35cf990f87d3245d01662cc550f4f3b43cc2dc58 100644 (file)
@@ -85,9 +85,14 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
        src_tcon = tlink_tcon(smb_file_src->tlink);
        target_tcon = tlink_tcon(smb_file_target->tlink);
 
-       /* check if source and target are on same tree connection */
-       if (src_tcon != target_tcon) {
-               cifs_dbg(VFS, "file copy src and target on different volume\n");
+       /* check source and target on same server (or volume if dup_extents) */
+       if (dup_extents && (src_tcon != target_tcon)) {
+               cifs_dbg(VFS, "source and target of copy not on same share\n");
+               goto out_fput;
+       }
+
+       if (!dup_extents && (src_tcon->ses != target_tcon->ses)) {
+               cifs_dbg(VFS, "source and target of copy not on same server\n");
                goto out_fput;
        }
 
index 2ab297dae5a7b2b4e544e3f35abc5f09b9fa7b1d..f9e766f464beec408b628146c4e0d4e04010e0f2 100644 (file)
@@ -43,6 +43,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
        struct smb2_file_all_info *smb2_data = NULL;
        __u8 smb2_oplock[17];
        struct cifs_fid *fid = oparms->fid;
+       struct network_resiliency_req nr_ioctl_req;
 
        smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
        if (smb2_path == NULL) {
@@ -67,6 +68,24 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
        if (rc)
                goto out;
 
+
+        if (oparms->tcon->use_resilient) {
+               nr_ioctl_req.Timeout = 0; /* use server default (120 seconds) */
+               nr_ioctl_req.Reserved = 0;
+               rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
+                       fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY, true,
+                       (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
+                       NULL, NULL /* no return info */);
+               if (rc == -EOPNOTSUPP) {
+                       cifs_dbg(VFS,
+                            "resiliency not supported by server, disabling\n");
+                       oparms->tcon->use_resilient = false;
+               } else if (rc)
+                       cifs_dbg(FYI, "error %d setting resiliency\n", rc);
+
+               rc = 0;
+       }
+
        if (buf) {
                /* open response does not have IndexNumber field - get it */
                rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
index 18da19f4f811ed19c327ab44a706e66c3a339bb0..53ccdde6ff187c16084e10dd07372d6516d25139 100644 (file)
@@ -810,7 +810,6 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
                            cfile->fid.volatile_fid, cfile->pid, &eof, false);
 }
 
-#ifdef CONFIG_CIFS_SMB311
 static int
 smb2_duplicate_extents(const unsigned int xid,
                        struct cifsFileInfo *srcfile,
@@ -854,8 +853,6 @@ smb2_duplicate_extents(const unsigned int xid,
 duplicate_extents_out:
        return rc;
 }
-#endif /* CONFIG_CIFS_SMB311 */
-
 
 static int
 smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
@@ -1703,6 +1700,7 @@ struct smb_version_operations smb30_operations = {
        .create_lease_buf = smb3_create_lease_buf,
        .parse_lease_buf = smb3_parse_lease_buf,
        .clone_range = smb2_clone_range,
+       .duplicate_extents = smb2_duplicate_extents,
        .validate_negotiate = smb3_validate_negotiate,
        .wp_retry_size = smb2_wp_retry_size,
        .dir_needs_close = smb2_dir_needs_close,
@@ -1840,7 +1838,7 @@ struct smb_version_values smb21_values = {
 struct smb_version_values smb30_values = {
        .version_string = SMB30_VERSION_STRING,
        .protocol_id = SMB30_PROT_ID,
-       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
+       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
        .large_lock_type = 0,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
@@ -1860,7 +1858,7 @@ struct smb_version_values smb30_values = {
 struct smb_version_values smb302_values = {
        .version_string = SMB302_VERSION_STRING,
        .protocol_id = SMB302_PROT_ID,
-       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
+       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
        .large_lock_type = 0,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
@@ -1881,7 +1879,7 @@ struct smb_version_values smb302_values = {
 struct smb_version_values smb311_values = {
        .version_string = SMB311_VERSION_STRING,
        .protocol_id = SMB311_PROT_ID,
-       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
+       .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU | SMB2_GLOBAL_CAP_PERSISTENT_HANDLES,
        .large_lock_type = 0,
        .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
        .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
index 61276929d139f64d1309481e69f2dfce2c8f1fe5..767555518d40ccd357b6f5540f2758bb8be6e654 100644 (file)
@@ -1151,13 +1151,130 @@ add_lease_context(struct TCP_Server_Info *server, struct kvec *iov,
        return 0;
 }
 
+static struct create_durable_v2 *
+create_durable_v2_buf(struct cifs_fid *pfid)
+{
+       struct create_durable_v2 *buf;
+
+       buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->ccontext.DataOffset = cpu_to_le16(offsetof
+                                       (struct create_durable_v2, dcontext));
+       buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2));
+       buf->ccontext.NameOffset = cpu_to_le16(offsetof
+                               (struct create_durable_v2, Name));
+       buf->ccontext.NameLength = cpu_to_le16(4);
+
+       buf->dcontext.Timeout = 0; /* Should this be configurable by workload */
+       buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
+       get_random_bytes(buf->dcontext.CreateGuid, 16);
+       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+
+       /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
+       buf->Name[0] = 'D';
+       buf->Name[1] = 'H';
+       buf->Name[2] = '2';
+       buf->Name[3] = 'Q';
+       return buf;
+}
+
+static struct create_durable_handle_reconnect_v2 *
+create_reconnect_durable_v2_buf(struct cifs_fid *fid)
+{
+       struct create_durable_handle_reconnect_v2 *buf;
+
+       buf = kzalloc(sizeof(struct create_durable_handle_reconnect_v2),
+                       GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->ccontext.DataOffset =
+               cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
+                                    dcontext));
+       buf->ccontext.DataLength =
+               cpu_to_le32(sizeof(struct durable_reconnect_context_v2));
+       buf->ccontext.NameOffset =
+               cpu_to_le16(offsetof(struct create_durable_handle_reconnect_v2,
+                           Name));
+       buf->ccontext.NameLength = cpu_to_le16(4);
+
+       buf->dcontext.Fid.PersistentFileId = fid->persistent_fid;
+       buf->dcontext.Fid.VolatileFileId = fid->volatile_fid;
+       buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
+       memcpy(buf->dcontext.CreateGuid, fid->create_guid, 16);
+
+       /* SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is "DH2C" */
+       buf->Name[0] = 'D';
+       buf->Name[1] = 'H';
+       buf->Name[2] = '2';
+       buf->Name[3] = 'C';
+       return buf;
+}
+
 static int
-add_durable_context(struct kvec *iov, unsigned int *num_iovec,
+add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
                    struct cifs_open_parms *oparms)
 {
        struct smb2_create_req *req = iov[0].iov_base;
        unsigned int num = *num_iovec;
 
+       iov[num].iov_base = create_durable_v2_buf(oparms->fid);
+       if (iov[num].iov_base == NULL)
+               return -ENOMEM;
+       iov[num].iov_len = sizeof(struct create_durable_v2);
+       if (!req->CreateContextsOffset)
+               req->CreateContextsOffset =
+                       cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
+                                                               iov[1].iov_len);
+       le32_add_cpu(&req->CreateContextsLength, sizeof(struct create_durable_v2));
+       inc_rfc1001_len(&req->hdr, sizeof(struct create_durable_v2));
+       *num_iovec = num + 1;
+       return 0;
+}
+
+static int
+add_durable_reconnect_v2_context(struct kvec *iov, unsigned int *num_iovec,
+                   struct cifs_open_parms *oparms)
+{
+       struct smb2_create_req *req = iov[0].iov_base;
+       unsigned int num = *num_iovec;
+
+       /* indicate that we don't need to relock the file */
+       oparms->reconnect = false;
+
+       iov[num].iov_base = create_reconnect_durable_v2_buf(oparms->fid);
+       if (iov[num].iov_base == NULL)
+               return -ENOMEM;
+       iov[num].iov_len = sizeof(struct create_durable_handle_reconnect_v2);
+       if (!req->CreateContextsOffset)
+               req->CreateContextsOffset =
+                       cpu_to_le32(sizeof(struct smb2_create_req) - 4 +
+                                                               iov[1].iov_len);
+       le32_add_cpu(&req->CreateContextsLength,
+                       sizeof(struct create_durable_handle_reconnect_v2));
+       inc_rfc1001_len(&req->hdr,
+                       sizeof(struct create_durable_handle_reconnect_v2));
+       *num_iovec = num + 1;
+       return 0;
+}
+
+static int
+add_durable_context(struct kvec *iov, unsigned int *num_iovec,
+                   struct cifs_open_parms *oparms, bool use_persistent)
+{
+       struct smb2_create_req *req = iov[0].iov_base;
+       unsigned int num = *num_iovec;
+
+       if (use_persistent) {
+               if (oparms->reconnect)
+                       return add_durable_reconnect_v2_context(iov, num_iovec,
+                                                               oparms);
+               else
+                       return add_durable_v2_context(iov, num_iovec, oparms);
+       }
+
        if (oparms->reconnect) {
                iov[num].iov_base = create_reconnect_durable_buf(oparms->fid);
                /* indicate that we don't need to relock the file */
@@ -1275,7 +1392,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
                        ccontext->Next =
                                cpu_to_le32(server->vals->create_lease_size);
                }
-               rc = add_durable_context(iov, &num_iovecs, oparms);
+
+               rc = add_durable_context(iov, &num_iovecs, oparms,
+                                       tcon->use_persistent);
                if (rc) {
                        cifs_small_buf_release(req);
                        kfree(copy_path);
index 451108284a2f438203568d90749f149ea567a602..4af52780ec350323cd41e993389e7214fb50f97d 100644 (file)
@@ -590,6 +590,44 @@ struct create_durable {
        } Data;
 } __packed;
 
+/* See MS-SMB2 2.2.13.2.11 */
+/* Flags */
+#define SMB2_DHANDLE_FLAG_PERSISTENT   0x00000002
+struct durable_context_v2 {
+       __le32 Timeout;
+       __le32 Flags;
+       __u64 Reserved;
+       __u8 CreateGuid[16];
+} __packed;
+
+struct create_durable_v2 {
+       struct create_context ccontext;
+       __u8   Name[8];
+       struct durable_context_v2 dcontext;
+} __packed;
+
+/* See MS-SMB2 2.2.13.2.12 */
+struct durable_reconnect_context_v2 {
+       struct {
+               __u64 PersistentFileId;
+               __u64 VolatileFileId;
+       } Fid;
+       __u8 CreateGuid[16];
+       __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
+} __packed;
+
+/* See MS-SMB2 2.2.14.2.12 */
+struct durable_reconnect_context_v2_rsp {
+       __le32 Timeout;
+       __le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
+} __packed;
+
+struct create_durable_handle_reconnect_v2 {
+       struct create_context ccontext;
+       __u8   Name[8];
+       struct durable_reconnect_context_v2 dcontext;
+} __packed;
+
 #define COPY_CHUNK_RES_KEY_SIZE        24
 struct resume_key_req {
        char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
@@ -643,6 +681,13 @@ struct fsctl_get_integrity_information_rsp {
 /* Integrity flags for above */
 #define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF  0x00000001
 
+/* See MS-SMB2 2.2.31.3 */
+struct network_resiliency_req {
+       __le32 Timeout;
+       __le32 Reserved;
+} __packed;
+/* There is no buffer for the response ie no struct network_resiliency_rsp */
+
 
 struct validate_negotiate_info_req {
        __le32 Capabilities;
index a639d0dab453373f4ae5dd2e2a6ee63f3867176d..f996daeea271142ede2bcb476226c66b1fe31f87 100644 (file)
@@ -90,7 +90,7 @@
 #define FSCTL_SRV_ENUMERATE_SNAPSHOTS 0x00144064
 /* Retrieve an opaque file reference for server-side data movement ie copy */
 #define FSCTL_SRV_REQUEST_RESUME_KEY 0x00140078
-#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4 /* BB add struct */
+#define FSCTL_LMR_REQUEST_RESILIENCY 0x001401D4
 #define FSCTL_LMR_GET_LINK_TRACK_INF 0x001400E8 /* BB add struct */
 #define FSCTL_LMR_SET_LINK_TRACK_INF 0x001400EC /* BB add struct */
 #define FSCTL_VALIDATE_NEGOTIATE_INFO 0x00140204
index c81ce7f200a6d9944b4670de2729f909048e773c..a7a1b218f308af56ac3094fa5f2ddb6b2749dd4a 100644 (file)
@@ -1636,6 +1636,116 @@ const struct file_operations configfs_dir_operations = {
        .iterate        = configfs_readdir,
 };
 
+/**
+ * configfs_register_group - creates a parent-child relation between two groups
+ * @parent_group:      parent group
+ * @group:             child group
+ *
+ * link groups, creates dentry for the child and attaches it to the
+ * parent dentry.
+ *
+ * Return: 0 on success, negative errno code on error
+ */
+int configfs_register_group(struct config_group *parent_group,
+                           struct config_group *group)
+{
+       struct configfs_subsystem *subsys = parent_group->cg_subsys;
+       struct dentry *parent;
+       int ret;
+
+       mutex_lock(&subsys->su_mutex);
+       link_group(parent_group, group);
+       mutex_unlock(&subsys->su_mutex);
+
+       parent = parent_group->cg_item.ci_dentry;
+
+       mutex_lock_nested(&d_inode(parent)->i_mutex, I_MUTEX_PARENT);
+       ret = create_default_group(parent_group, group);
+       if (!ret) {
+               spin_lock(&configfs_dirent_lock);
+               configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata);
+               spin_unlock(&configfs_dirent_lock);
+       }
+       mutex_unlock(&d_inode(parent)->i_mutex);
+       return ret;
+}
+EXPORT_SYMBOL(configfs_register_group);
+
+/**
+ * configfs_unregister_group() - unregisters a child group from its parent
+ * @group: parent group to be unregistered
+ *
+ * Undoes configfs_register_group()
+ */
+void configfs_unregister_group(struct config_group *group)
+{
+       struct configfs_subsystem *subsys = group->cg_subsys;
+       struct dentry *dentry = group->cg_item.ci_dentry;
+       struct dentry *parent = group->cg_item.ci_parent->ci_dentry;
+
+       mutex_lock_nested(&d_inode(parent)->i_mutex, I_MUTEX_PARENT);
+       spin_lock(&configfs_dirent_lock);
+       configfs_detach_prep(dentry, NULL);
+       spin_unlock(&configfs_dirent_lock);
+
+       configfs_detach_group(&group->cg_item);
+       d_inode(dentry)->i_flags |= S_DEAD;
+       dont_mount(dentry);
+       d_delete(dentry);
+       mutex_unlock(&d_inode(parent)->i_mutex);
+
+       dput(dentry);
+
+       mutex_lock(&subsys->su_mutex);
+       unlink_group(group);
+       mutex_unlock(&subsys->su_mutex);
+}
+EXPORT_SYMBOL(configfs_unregister_group);
+
+/**
+ * configfs_register_default_group() - allocates and registers a child group
+ * @parent_group:      parent group
+ * @name:              child group name
+ * @item_type:         child item type description
+ *
+ * boilerplate to allocate and register a child group with its parent. We need
+ * kzalloc'ed memory because child's default_group is initially empty.
+ *
+ * Return: allocated config group or ERR_PTR() on error
+ */
+struct config_group *
+configfs_register_default_group(struct config_group *parent_group,
+                               const char *name,
+                               struct config_item_type *item_type)
+{
+       int ret;
+       struct config_group *group;
+
+       group = kzalloc(sizeof(*group), GFP_KERNEL);
+       if (!group)
+               return ERR_PTR(-ENOMEM);
+       config_group_init_type_name(group, name, item_type);
+
+       ret = configfs_register_group(parent_group, group);
+       if (ret) {
+               kfree(group);
+               return ERR_PTR(ret);
+       }
+       return group;
+}
+EXPORT_SYMBOL(configfs_register_default_group);
+
+/**
+ * configfs_unregister_default_group() - unregisters and frees a child group
+ * @group:     the group to act on
+ */
+void configfs_unregister_default_group(struct config_group *group)
+{
+       configfs_unregister_group(group);
+       kfree(group);
+}
+EXPORT_SYMBOL(configfs_unregister_default_group);
+
 int configfs_register_subsystem(struct configfs_subsystem *subsys)
 {
        int err;
index 403269ffcdf3518b45f878166270c12e3365c17e..d39099ea7df76d723e4501c316eb43352b11e69c 100644 (file)
@@ -65,7 +65,6 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
 {
        struct configfs_attribute * attr = to_attr(dentry);
        struct config_item * item = to_item(dentry->d_parent);
-       struct configfs_item_operations * ops = buffer->ops;
        int ret = 0;
        ssize_t count;
 
@@ -74,7 +73,8 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
        if (!buffer->page)
                return -ENOMEM;
 
-       count = ops->show_attribute(item,attr,buffer->page);
+       count = attr->show(item, buffer->page);
+
        buffer->needs_read_fill = 0;
        BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
        if (count >= 0)
@@ -171,9 +171,8 @@ flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size
 {
        struct configfs_attribute * attr = to_attr(dentry);
        struct config_item * item = to_item(dentry->d_parent);
-       struct configfs_item_operations * ops = buffer->ops;
 
-       return ops->store_attribute(item,attr,buffer->page,count);
+       return attr->store(item, buffer->page, count);
 }
 
 
@@ -237,8 +236,7 @@ static int check_perm(struct inode * inode, struct file * file)
         * and we must have a store method.
         */
        if (file->f_mode & FMODE_WRITE) {
-
-               if (!(inode->i_mode & S_IWUGO) || !ops->store_attribute)
+               if (!(inode->i_mode & S_IWUGO) || !attr->store)
                        goto Eaccess;
 
        }
@@ -248,7 +246,7 @@ static int check_perm(struct inode * inode, struct file * file)
         * must be a show method for it.
         */
        if (file->f_mode & FMODE_READ) {
-               if (!(inode->i_mode & S_IRUGO) || !ops->show_attribute)
+               if (!(inode->i_mode & S_IRUGO) || !attr->show)
                        goto Eaccess;
        }
 
index 131fd35ae39d53f8a9ef7bdd1aaa61677beda5f0..43671b68220ed968386f5c1ad9067f236fbab67e 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -174,8 +174,10 @@ static ssize_t dax_io(struct inode *inode, struct iov_iter *iter,
                else
                        len = iov_iter_zero(max - pos, iter);
 
-               if (!len)
+               if (!len) {
+                       retval = -EFAULT;
                        break;
+               }
 
                pos += len;
                addr += len;
@@ -539,6 +541,10 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
        unsigned long pfn;
        int result = 0;
 
+       /* dax pmd mappings are broken wrt gup and fork */
+       if (!IS_ENABLED(CONFIG_FS_DAX_PMD))
+               return VM_FAULT_FALLBACK;
+
        /* Fall back to PTEs if we're going to COW */
        if (write && !(vma->vm_flags & VM_SHARED))
                return VM_FAULT_FALLBACK;
@@ -627,6 +633,13 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
                if ((length < PMD_SIZE) || (pfn & PG_PMD_COLOUR))
                        goto fallback;
 
+               /*
+                * TODO: teach vmf_insert_pfn_pmd() to support
+                * 'pte_special' for pmds
+                */
+               if (pfn_valid(pfn))
+                       goto fallback;
+
                if (buffer_unwritten(&bh) || buffer_new(&bh)) {
                        int i;
                        for (i = 0; i < PTRS_PER_PMD; i++)
index d521bddf876dce012927937f83546db31a3426e7..8e294fbbac392c9bacdc6ee886be7ba3e80cd070 100644 (file)
@@ -61,35 +61,8 @@ static struct config_item *make_node(struct config_group *, const char *);
 static void drop_node(struct config_group *, struct config_item *);
 static void release_node(struct config_item *);
 
-static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
-                           char *buf);
-static ssize_t store_cluster(struct config_item *i,
-                            struct configfs_attribute *a,
-                            const char *buf, size_t len);
-static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
-                        char *buf);
-static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
-                         const char *buf, size_t len);
-static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
-                        char *buf);
-static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
-                         const char *buf, size_t len);
-
-static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf);
-static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
-                               size_t len);
-static ssize_t comm_local_read(struct dlm_comm *cm, char *buf);
-static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
-                               size_t len);
-static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf,
-                               size_t len);
-static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf);
-static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf);
-static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
-                               size_t len);
-static ssize_t node_weight_read(struct dlm_node *nd, char *buf);
-static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
-                               size_t len);
+static struct configfs_attribute *comm_attrs[];
+static struct configfs_attribute *node_attrs[];
 
 struct dlm_cluster {
        struct config_group group;
@@ -108,6 +81,12 @@ struct dlm_cluster {
        char cl_cluster_name[DLM_LOCKSPACE_LEN];
 };
 
+static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
+{
+       return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
+                  NULL;
+}
+
 enum {
        CLUSTER_ATTR_TCP_PORT = 0,
        CLUSTER_ATTR_BUFFER_SIZE,
@@ -124,33 +103,24 @@ enum {
        CLUSTER_ATTR_CLUSTER_NAME,
 };
 
-struct cluster_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct dlm_cluster *, char *);
-       ssize_t (*store)(struct dlm_cluster *, const char *, size_t);
-};
-
-static ssize_t cluster_cluster_name_read(struct dlm_cluster *cl, char *buf)
+static ssize_t cluster_cluster_name_show(struct config_item *item, char *buf)
 {
+       struct dlm_cluster *cl = config_item_to_cluster(item);
        return sprintf(buf, "%s\n", cl->cl_cluster_name);
 }
 
-static ssize_t cluster_cluster_name_write(struct dlm_cluster *cl,
+static ssize_t cluster_cluster_name_store(struct config_item *item,
                                          const char *buf, size_t len)
 {
+       struct dlm_cluster *cl = config_item_to_cluster(item);
+
        strlcpy(dlm_config.ci_cluster_name, buf,
                                sizeof(dlm_config.ci_cluster_name));
        strlcpy(cl->cl_cluster_name, buf, sizeof(cl->cl_cluster_name));
        return len;
 }
 
-static struct cluster_attribute cluster_attr_cluster_name = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "cluster_name",
-                    .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = cluster_cluster_name_read,
-       .store  = cluster_cluster_name_write,
-};
+CONFIGFS_ATTR(cluster_, cluster_name);
 
 static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
                           int *info_field, int check_zero,
@@ -175,17 +145,19 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
 }
 
 #define CLUSTER_ATTR(name, check_zero)                                        \
-static ssize_t name##_write(struct dlm_cluster *cl, const char *buf, size_t len) \
+static ssize_t cluster_##name##_store(struct config_item *item, \
+               const char *buf, size_t len) \
 {                                                                             \
+       struct dlm_cluster *cl = config_item_to_cluster(item);                \
        return cluster_set(cl, &cl->cl_##name, &dlm_config.ci_##name,         \
                           check_zero, buf, len);                             \
 }                                                                             \
-static ssize_t name##_read(struct dlm_cluster *cl, char *buf)                 \
+static ssize_t cluster_##name##_show(struct config_item *item, char *buf)     \
 {                                                                             \
+       struct dlm_cluster *cl = config_item_to_cluster(item);                \
        return snprintf(buf, PAGE_SIZE, "%u\n", cl->cl_##name);               \
 }                                                                             \
-static struct cluster_attribute cluster_attr_##name =                         \
-__CONFIGFS_ATTR(name, 0644, name##_read, name##_write)
+CONFIGFS_ATTR(cluster_, name);
 
 CLUSTER_ATTR(tcp_port, 1);
 CLUSTER_ATTR(buffer_size, 1);
@@ -201,19 +173,19 @@ CLUSTER_ATTR(new_rsb_count, 0);
 CLUSTER_ATTR(recover_callbacks, 0);
 
 static struct configfs_attribute *cluster_attrs[] = {
-       [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
-       [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size.attr,
-       [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size.attr,
-       [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer.attr,
-       [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs.attr,
-       [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
-       [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
-       [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
-       [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
-       [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr,
-       [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count.attr,
-       [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks.attr,
-       [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name.attr,
+       [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port,
+       [CLUSTER_ATTR_BUFFER_SIZE] = &cluster_attr_buffer_size,
+       [CLUSTER_ATTR_RSBTBL_SIZE] = &cluster_attr_rsbtbl_size,
+       [CLUSTER_ATTR_RECOVER_TIMER] = &cluster_attr_recover_timer,
+       [CLUSTER_ATTR_TOSS_SECS] = &cluster_attr_toss_secs,
+       [CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs,
+       [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug,
+       [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol,
+       [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs,
+       [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us,
+       [CLUSTER_ATTR_NEW_RSB_COUNT] = &cluster_attr_new_rsb_count,
+       [CLUSTER_ATTR_RECOVER_CALLBACKS] = &cluster_attr_recover_callbacks,
+       [CLUSTER_ATTR_CLUSTER_NAME] = &cluster_attr_cluster_name,
        NULL,
 };
 
@@ -224,83 +196,11 @@ enum {
        COMM_ATTR_ADDR_LIST,
 };
 
-struct comm_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct dlm_comm *, char *);
-       ssize_t (*store)(struct dlm_comm *, const char *, size_t);
-};
-
-static struct comm_attribute comm_attr_nodeid = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "nodeid",
-                    .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = comm_nodeid_read,
-       .store  = comm_nodeid_write,
-};
-
-static struct comm_attribute comm_attr_local = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "local",
-                    .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = comm_local_read,
-       .store  = comm_local_write,
-};
-
-static struct comm_attribute comm_attr_addr = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "addr",
-                    .ca_mode = S_IWUSR },
-       .store  = comm_addr_write,
-};
-
-static struct comm_attribute comm_attr_addr_list = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "addr_list",
-                    .ca_mode = S_IRUGO },
-       .show   = comm_addr_list_read,
-};
-
-static struct configfs_attribute *comm_attrs[] = {
-       [COMM_ATTR_NODEID] = &comm_attr_nodeid.attr,
-       [COMM_ATTR_LOCAL] = &comm_attr_local.attr,
-       [COMM_ATTR_ADDR] = &comm_attr_addr.attr,
-       [COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list.attr,
-       NULL,
-};
-
 enum {
        NODE_ATTR_NODEID = 0,
        NODE_ATTR_WEIGHT,
 };
 
-struct node_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct dlm_node *, char *);
-       ssize_t (*store)(struct dlm_node *, const char *, size_t);
-};
-
-static struct node_attribute node_attr_nodeid = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "nodeid",
-                    .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = node_nodeid_read,
-       .store  = node_nodeid_write,
-};
-
-static struct node_attribute node_attr_weight = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                    .ca_name = "weight",
-                    .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = node_weight_read,
-       .store  = node_weight_write,
-};
-
-static struct configfs_attribute *node_attrs[] = {
-       [NODE_ATTR_NODEID] = &node_attr_nodeid.attr,
-       [NODE_ATTR_WEIGHT] = &node_attr_weight.attr,
-       NULL,
-};
-
 struct dlm_clusters {
        struct configfs_subsystem subsys;
 };
@@ -349,8 +249,6 @@ static struct configfs_group_operations clusters_ops = {
 
 static struct configfs_item_operations cluster_ops = {
        .release = release_cluster,
-       .show_attribute = show_cluster,
-       .store_attribute = store_cluster,
 };
 
 static struct configfs_group_operations spaces_ops = {
@@ -369,8 +267,6 @@ static struct configfs_group_operations comms_ops = {
 
 static struct configfs_item_operations comm_ops = {
        .release = release_comm,
-       .show_attribute = show_comm,
-       .store_attribute = store_comm,
 };
 
 static struct configfs_group_operations nodes_ops = {
@@ -380,8 +276,6 @@ static struct configfs_group_operations nodes_ops = {
 
 static struct configfs_item_operations node_ops = {
        .release = release_node,
-       .show_attribute = show_node,
-       .store_attribute = store_node,
 };
 
 static struct config_item_type clusters_type = {
@@ -427,12 +321,6 @@ static struct config_item_type node_type = {
        .ct_owner = THIS_MODULE,
 };
 
-static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
-{
-       return i ? container_of(to_config_group(i), struct dlm_cluster, group) :
-                  NULL;
-}
-
 static struct dlm_space *config_item_to_space(struct config_item *i)
 {
        return i ? container_of(to_config_group(i), struct dlm_space, group) :
@@ -687,66 +575,30 @@ void dlm_config_exit(void)
  * Functions for user space to read/write attributes
  */
 
-static ssize_t show_cluster(struct config_item *i, struct configfs_attribute *a,
-                           char *buf)
-{
-       struct dlm_cluster *cl = config_item_to_cluster(i);
-       struct cluster_attribute *cla =
-                       container_of(a, struct cluster_attribute, attr);
-       return cla->show ? cla->show(cl, buf) : 0;
-}
-
-static ssize_t store_cluster(struct config_item *i,
-                            struct configfs_attribute *a,
-                            const char *buf, size_t len)
+static ssize_t comm_nodeid_show(struct config_item *item, char *buf)
 {
-       struct dlm_cluster *cl = config_item_to_cluster(i);
-       struct cluster_attribute *cla =
-               container_of(a, struct cluster_attribute, attr);
-       return cla->store ? cla->store(cl, buf, len) : -EINVAL;
-}
-
-static ssize_t show_comm(struct config_item *i, struct configfs_attribute *a,
-                        char *buf)
-{
-       struct dlm_comm *cm = config_item_to_comm(i);
-       struct comm_attribute *cma =
-                       container_of(a, struct comm_attribute, attr);
-       return cma->show ? cma->show(cm, buf) : 0;
-}
-
-static ssize_t store_comm(struct config_item *i, struct configfs_attribute *a,
-                         const char *buf, size_t len)
-{
-       struct dlm_comm *cm = config_item_to_comm(i);
-       struct comm_attribute *cma =
-               container_of(a, struct comm_attribute, attr);
-       return cma->store ? cma->store(cm, buf, len) : -EINVAL;
+       return sprintf(buf, "%d\n", config_item_to_comm(item)->nodeid);
 }
 
-static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
-{
-       return sprintf(buf, "%d\n", cm->nodeid);
-}
-
-static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
+static ssize_t comm_nodeid_store(struct config_item *item, const char *buf,
                                 size_t len)
 {
-       int rc = kstrtoint(buf, 0, &cm->nodeid);
+       int rc = kstrtoint(buf, 0, &config_item_to_comm(item)->nodeid);
 
        if (rc)
                return rc;
        return len;
 }
 
-static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
+static ssize_t comm_local_show(struct config_item *item, char *buf)
 {
-       return sprintf(buf, "%d\n", cm->local);
+       return sprintf(buf, "%d\n", config_item_to_comm(item)->local);
 }
 
-static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
+static ssize_t comm_local_store(struct config_item *item, const char *buf,
                                size_t len)
 {
+       struct dlm_comm *cm = config_item_to_comm(item);
        int rc = kstrtoint(buf, 0, &cm->local);
 
        if (rc)
@@ -756,8 +608,10 @@ static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
        return len;
 }
 
-static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
+static ssize_t comm_addr_store(struct config_item *item, const char *buf,
+               size_t len)
 {
+       struct dlm_comm *cm = config_item_to_comm(item);
        struct sockaddr_storage *addr;
        int rv;
 
@@ -783,8 +637,9 @@ static ssize_t comm_addr_write(struct dlm_comm *cm, const char *buf, size_t len)
        return len;
 }
 
-static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
+static ssize_t comm_addr_list_show(struct config_item *item, char *buf)
 {
+       struct dlm_comm *cm = config_item_to_comm(item);
        ssize_t s;
        ssize_t allowance;
        int i;
@@ -827,32 +682,28 @@ static ssize_t comm_addr_list_read(struct dlm_comm *cm, char *buf)
        return 4096 - allowance;
 }
 
-static ssize_t show_node(struct config_item *i, struct configfs_attribute *a,
-                        char *buf)
-{
-       struct dlm_node *nd = config_item_to_node(i);
-       struct node_attribute *nda =
-                       container_of(a, struct node_attribute, attr);
-       return nda->show ? nda->show(nd, buf) : 0;
-}
+CONFIGFS_ATTR(comm_, nodeid);
+CONFIGFS_ATTR(comm_, local);
+CONFIGFS_ATTR_WO(comm_, addr);
+CONFIGFS_ATTR_RO(comm_, addr_list);
 
-static ssize_t store_node(struct config_item *i, struct configfs_attribute *a,
-                         const char *buf, size_t len)
-{
-       struct dlm_node *nd = config_item_to_node(i);
-       struct node_attribute *nda =
-               container_of(a, struct node_attribute, attr);
-       return nda->store ? nda->store(nd, buf, len) : -EINVAL;
-}
+static struct configfs_attribute *comm_attrs[] = {
+       [COMM_ATTR_NODEID] = &comm_attr_nodeid,
+       [COMM_ATTR_LOCAL] = &comm_attr_local,
+       [COMM_ATTR_ADDR] = &comm_attr_addr,
+       [COMM_ATTR_ADDR_LIST] = &comm_attr_addr_list,
+       NULL,
+};
 
-static ssize_t node_nodeid_read(struct dlm_node *nd, char *buf)
+static ssize_t node_nodeid_show(struct config_item *item, char *buf)
 {
-       return sprintf(buf, "%d\n", nd->nodeid);
+       return sprintf(buf, "%d\n", config_item_to_node(item)->nodeid);
 }
 
-static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
+static ssize_t node_nodeid_store(struct config_item *item, const char *buf,
                                 size_t len)
 {
+       struct dlm_node *nd = config_item_to_node(item);
        uint32_t seq = 0;
        int rc = kstrtoint(buf, 0, &nd->nodeid);
 
@@ -863,21 +714,30 @@ static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
        return len;
 }
 
-static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
+static ssize_t node_weight_show(struct config_item *item, char *buf)
 {
-       return sprintf(buf, "%d\n", nd->weight);
+       return sprintf(buf, "%d\n", config_item_to_node(item)->weight);
 }
 
-static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
+static ssize_t node_weight_store(struct config_item *item, const char *buf,
                                 size_t len)
 {
-       int rc = kstrtoint(buf, 0, &nd->weight);
+       int rc = kstrtoint(buf, 0, &config_item_to_node(item)->weight);
 
        if (rc)
                return rc;
        return len;
 }
 
+CONFIGFS_ATTR(node_, nodeid);
+CONFIGFS_ATTR(node_, weight);
+
+static struct configfs_attribute *node_attrs[] = {
+       [NODE_ATTR_NODEID] = &node_attr_nodeid,
+       [NODE_ATTR_WEIGHT] = &node_attr_weight,
+       NULL,
+};
+
 /*
  * Functions for the dlm to get the info that's been configured
  */
index 3a71cea684208f16beb587f61989bfffb0a0d006..748d35afc90266123407d61d7aed944f2e9ad9ca 100644 (file)
@@ -569,6 +569,8 @@ static int parse_options(char *options, struct super_block *sb)
                        /* Fall through */
                case Opt_dax:
 #ifdef CONFIG_FS_DAX
+                       ext2_msg(sb, KERN_WARNING,
+               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
                        set_opt(sbi->s_mount_opt, DAX);
 #else
                        ext2_msg(sb, KERN_INFO, "dax option not supported");
index 0b6bfd3a398bd320cf8bbbbe81745f364decd765..fa70848afa8f4c403e988d058966db0b6af456b6 100644 (file)
@@ -293,10 +293,9 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
                        ext2_xattr_handler(entry->e_name_index);
 
                if (handler) {
-                       size_t size = handler->list(dentry, buffer, rest,
-                                                   entry->e_name,
-                                                   entry->e_name_len,
-                                                   handler->flags);
+                       size_t size = handler->list(handler, dentry, buffer,
+                                                   rest, entry->e_name,
+                                                   entry->e_name_len);
                        if (buffer) {
                                if (size > rest) {
                                        error = -ERANGE;
index 702fc6840246e7484e5cc3d4c553c9dd2fa5d37e..dfb08750370d85d71a7fc89bef68345229b7740d 100644 (file)
@@ -8,8 +8,9 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-                        const char *name, size_t name_len, int type)
+ext2_xattr_security_list(const struct xattr_handler *handler,
+                        struct dentry *dentry, char *list, size_t list_size,
+                        const char *name, size_t name_len)
 {
        const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -23,8 +24,9 @@ ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_security_get(struct dentry *dentry, const char *name,
-                      void *buffer, size_t size, int type)
+ext2_xattr_security_get(const struct xattr_handler *handler,
+                       struct dentry *dentry, const char *name,
+                       void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -33,8 +35,9 @@ ext2_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int
-ext2_xattr_security_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+ext2_xattr_security_set(const struct xattr_handler *handler,
+                       struct dentry *dentry, const char *name,
+                       const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index 42b6e9874bccf5501737ac53e62228ce22a6e3dd..3150dd3a78595084d0a6bfd5916f86272e68303a 100644 (file)
@@ -9,8 +9,9 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
+ext2_xattr_trusted_list(const struct xattr_handler *handler,
+                       struct dentry *dentry, char *list, size_t list_size,
+                       const char *name, size_t name_len)
 {
        const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -27,8 +28,9 @@ ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+ext2_xattr_trusted_get(const struct xattr_handler *handler,
+                      struct dentry *dentry, const char *name,
+                      void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -37,8 +39,9 @@ ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
 }
 
 static int
-ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+ext2_xattr_trusted_set(const struct xattr_handler *handler,
+                      struct dentry *dentry, const char *name,
+                      const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index ecdc4605192cef4d502e6633e5537b5d06117a45..339a49bbb8efbee752138fc600399c712d1b98a7 100644 (file)
@@ -11,8 +11,9 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
+ext2_xattr_user_list(const struct xattr_handler *handler,
+                    struct dentry *dentry, char *list, size_t list_size,
+                    const char *name, size_t name_len)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -29,8 +30,9 @@ ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext2_xattr_user_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+ext2_xattr_user_get(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -41,8 +43,9 @@ ext2_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int
-ext2_xattr_user_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+ext2_xattr_user_set(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index 753f4e68b820da0dd78fc7a7e3a66e529846ea0b..c9ab67da6e5abbe871ce4bc7760c007e07f2b479 100644 (file)
@@ -1664,8 +1664,12 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                }
                sbi->s_jquota_fmt = m->mount_opt;
 #endif
-#ifndef CONFIG_FS_DAX
        } else if (token == Opt_dax) {
+#ifdef CONFIG_FS_DAX
+               ext4_msg(sb, KERN_WARNING,
+               "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+                       sbi->s_mount_opt |= m->mount_opt;
+#else
                ext4_msg(sb, KERN_INFO, "dax option not supported");
                return -1;
 #endif
index 984448c6f5f0af1d429a982cce28f7ab26b3b093..6b6b3e751f8c77ebc9089c412f9019b4774a4301 100644 (file)
@@ -405,10 +405,9 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
                        ext4_xattr_handler(entry->e_name_index);
 
                if (handler) {
-                       size_t size = handler->list(dentry, buffer, rest,
-                                                   entry->e_name,
-                                                   entry->e_name_len,
-                                                   handler->flags);
+                       size_t size = handler->list(handler, dentry, buffer,
+                                                   rest, entry->e_name,
+                                                   entry->e_name_len);
                        if (buffer) {
                                if (size > rest)
                                        return -ERANGE;
index 95d90e0560f05677279db254936a4fa086ad67d2..36f4c1a84c218307a1ae5c7e5c9805747025cf38 100644 (file)
@@ -12,8 +12,9 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
+ext4_xattr_security_list(const struct xattr_handler *handler,
+                        struct dentry *dentry, char *list, size_t list_size,
+                        const char *name, size_t name_len)
 {
        const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
        const size_t total_len = prefix_len + name_len + 1;
@@ -28,8 +29,9 @@ ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_security_get(struct dentry *dentry, const char *name,
-                      void *buffer, size_t size, int type)
+ext4_xattr_security_get(const struct xattr_handler *handler,
+                       struct dentry *dentry, const char *name,
+                       void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -38,8 +40,9 @@ ext4_xattr_security_get(struct dentry *dentry, const char *name,
 }
 
 static int
-ext4_xattr_security_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+ext4_xattr_security_set(const struct xattr_handler *handler,
+                       struct dentry *dentry, const char *name,
+                       const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index 891ee2ddfbd64a7b5f5201f6252edaafb3550b97..4880890533424ca63e67fc8ce0536254ce669028 100644 (file)
@@ -13,8 +13,9 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
+ext4_xattr_trusted_list(const struct xattr_handler *handler,
+                       struct dentry *dentry, char *list, size_t list_size,
+                       const char *name, size_t name_len)
 {
        const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -31,8 +32,9 @@ ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
-               size_t size, int type)
+ext4_xattr_trusted_get(const struct xattr_handler *handler,
+                      struct dentry *dentry, const char *name, void *buffer,
+                      size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -41,8 +43,9 @@ ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
 }
 
 static int
-ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+ext4_xattr_trusted_set(const struct xattr_handler *handler,
+                      struct dentry *dentry, const char *name,
+                      const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index 6ed932b3c04359b0817698ebcfcaf4a2d007b03f..d2dec33640620024aae408cdb394f4689d23dd87 100644 (file)
@@ -12,8 +12,9 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
-                    const char *name, size_t name_len, int type)
+ext4_xattr_user_list(const struct xattr_handler *handler,
+                    struct dentry *dentry, char *list, size_t list_size,
+                    const char *name, size_t name_len)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -30,8 +31,9 @@ ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
 }
 
 static int
-ext4_xattr_user_get(struct dentry *dentry, const char *name,
-                   void *buffer, size_t size, int type)
+ext4_xattr_user_get(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -42,8 +44,9 @@ ext4_xattr_user_get(struct dentry *dentry, const char *name,
 }
 
 static int
-ext4_xattr_user_set(struct dentry *dentry, const char *name,
-                   const void *value, size_t size, int flags, int type)
+ext4_xattr_user_set(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
index 4de2286c0e4df6e226922b181e92929dc81bb7ca..862368a32e5354c3d9458f39f933e87d05c3e287 100644 (file)
 #include "f2fs.h"
 #include "xattr.h"
 
-static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t len, int type)
+static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler,
+               struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t len)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
-       int total_len, prefix_len = 0;
-       const char *prefix = NULL;
+       int total_len, prefix_len;
 
-       switch (type) {
+       switch (handler->flags) {
        case F2FS_XATTR_INDEX_USER:
                if (!test_opt(sbi, XATTR_USER))
                        return -EOPNOTSUPP;
-               prefix = XATTR_USER_PREFIX;
-               prefix_len = XATTR_USER_PREFIX_LEN;
                break;
        case F2FS_XATTR_INDEX_TRUSTED:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               prefix = XATTR_TRUSTED_PREFIX;
-               prefix_len = XATTR_TRUSTED_PREFIX_LEN;
                break;
        case F2FS_XATTR_INDEX_SECURITY:
-               prefix = XATTR_SECURITY_PREFIX;
-               prefix_len = XATTR_SECURITY_PREFIX_LEN;
                break;
        default:
                return -EINVAL;
        }
 
+       prefix_len = strlen(handler->prefix);
        total_len = prefix_len + len + 1;
        if (list && total_len <= list_size) {
-               memcpy(list, prefix, prefix_len);
+               memcpy(list, handler->prefix, prefix_len);
                memcpy(list + prefix_len, name, len);
                list[prefix_len + len] = '\0';
        }
        return total_len;
 }
 
-static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
+               struct dentry *dentry, const char *name, void *buffer,
+               size_t size)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-       switch (type) {
+       switch (handler->flags) {
        case F2FS_XATTR_INDEX_USER:
                if (!test_opt(sbi, XATTR_USER))
                        return -EOPNOTSUPP;
@@ -83,15 +79,17 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
        }
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL);
+       return f2fs_getxattr(d_inode(dentry), handler->flags, name,
+                            buffer, size, NULL);
 }
 
-static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
+               struct dentry *dentry, const char *name, const void *value,
+               size_t size, int flags)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
 
-       switch (type) {
+       switch (handler->flags) {
        case F2FS_XATTR_INDEX_USER:
                if (!test_opt(sbi, XATTR_USER))
                        return -EOPNOTSUPP;
@@ -108,27 +106,26 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return f2fs_setxattr(d_inode(dentry), type, name,
+       return f2fs_setxattr(d_inode(dentry), handler->flags, name,
                                        value, size, NULL, flags);
 }
 
-static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t len, int type)
+static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler,
+               struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t len)
 {
        const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
        size_t size;
 
-       if (type != F2FS_XATTR_INDEX_ADVISE)
-               return 0;
-
        size = strlen(xname) + 1;
        if (list && size <= list_size)
                memcpy(list, xname, size);
        return size;
 }
 
-static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
+               struct dentry *dentry, const char *name, void *buffer,
+               size_t size)
 {
        struct inode *inode = d_inode(dentry);
 
@@ -140,8 +137,9 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
        return sizeof(char);
 }
 
-static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
+               struct dentry *dentry, const char *name, const void *value,
+               size_t size, int flags)
 {
        struct inode *inode = d_inode(dentry);
 
@@ -462,8 +460,8 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
                if (!handler)
                        continue;
 
-               size = handler->list(dentry, buffer, rest, entry->e_name,
-                               entry->e_name_len, handler->flags);
+               size = handler->list(handler, dentry, buffer, rest,
+                                    entry->e_name, entry->e_name_len);
                if (buffer && size > rest) {
                        error = -ERANGE;
                        goto cleanup;
index 4afc4d9d2e4127debe45cb51b5f1fc17d16fee4d..8b2127ffb226cca2ece880d41fd756624c5d3118 100644 (file)
@@ -610,9 +610,9 @@ static int __fat_readdir(struct inode *inode, struct file *file,
                int status = fat_parse_long(inode, &cpos, &bh, &de,
                                            &unicode, &nr_slots);
                if (status < 0) {
-                       ctx->pos = cpos;
+                       bh = NULL;
                        ret = status;
-                       goto out;
+                       goto end_of_dir;
                } else if (status == PARSE_INVALID)
                        goto record_end;
                else if (status == PARSE_NOT_LONGNAME)
@@ -654,8 +654,9 @@ static int __fat_readdir(struct inode *inode, struct file *file,
        fill_len = short_len;
 
 start_filldir:
-       if (!fake_offset)
-               ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
+       ctx->pos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
+       if (fake_offset && ctx->pos < 2)
+               ctx->pos = 2;
 
        if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) {
                if (!dir_emit_dot(file, ctx))
@@ -681,14 +682,19 @@ static int __fat_readdir(struct inode *inode, struct file *file,
        fake_offset = 0;
        ctx->pos = cpos;
        goto get_new;
+
 end_of_dir:
-       ctx->pos = cpos;
+       if (fake_offset && cpos < 2)
+               ctx->pos = 2;
+       else
+               ctx->pos = cpos;
 fill_failed:
        brelse(bh);
        if (unicode)
                __putname(unicode);
 out:
        mutex_unlock(&sbi->s_lock);
+
        return ret;
 }
 
index 4c096fa9e2a18c4c52ef528c96198d9a08ef9b6a..53ce76a374fe7313314eafd274b8a58db81b52d0 100644 (file)
@@ -583,11 +583,13 @@ int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata)
  *
  * Returns: actual size of data on success, -errno on error
  */
-static int gfs2_xattr_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int gfs2_xattr_get(const struct xattr_handler *handler,
+                         struct dentry *dentry, const char *name,
+                         void *buffer, size_t size)
 {
        struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
        struct gfs2_ea_location el;
+       int type = handler->flags;
        int error;
 
        if (!ip->i_eattr)
@@ -1227,11 +1229,12 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
        return error;
 }
 
-static int gfs2_xattr_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int gfs2_xattr_set(const struct xattr_handler *handler,
+                         struct dentry *dentry, const char *name,
+                         const void *value, size_t size, int flags)
 {
        return __gfs2_xattr_set(d_inode(dentry), name, value,
-                               size, flags, type);
+                               size, flags, handler->flags);
 }
 
 
index 416b1dbafe516583b22efad4a851e7f6cf2abb25..e41a010cd89ca6ca8e76dec51d2d8914782e1db6 100644 (file)
@@ -849,8 +849,9 @@ static int hfsplus_removexattr(struct inode *inode, const char *name)
        return err;
 }
 
-static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
-                                       void *buffer, size_t size, int type)
+static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
+                               struct dentry *dentry, const char *name,
+                               void *buffer, size_t size)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -871,8 +872,9 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
        return __hfsplus_getxattr(d_inode(dentry), name, buffer, size);
 }
 
-static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
+                               struct dentry *dentry, const char *name,
+                               const void *buffer, size_t size, int flags)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -893,19 +895,8 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
        return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       /*
-        * This method is not used.
-        * It is used hfsplus_listxattr() instead of generic_listxattr().
-        */
-       return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_osx_handler = {
        .prefix = XATTR_MAC_OSX_PREFIX,
-       .list   = hfsplus_osx_listxattr,
        .get    = hfsplus_osx_getxattr,
        .set    = hfsplus_osx_setxattr,
 };
index aacff00a9ff9e77c5d6f6cca250dc90cf4e1cbfc..72a68a3a0c996e1ca73fb2ec462c30f19b56f247 100644 (file)
 #include "xattr.h"
 #include "acl.h"
 
-static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
-                                       void *buffer, size_t size, int type)
+static int hfsplus_security_getxattr(const struct xattr_handler *handler,
+                                    struct dentry *dentry, const char *name,
+                                    void *buffer, size_t size)
 {
        return hfsplus_getxattr(dentry, name, buffer, size,
                                XATTR_SECURITY_PREFIX,
                                XATTR_SECURITY_PREFIX_LEN);
 }
 
-static int hfsplus_security_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int hfsplus_security_setxattr(const struct xattr_handler *handler,
+                                    struct dentry *dentry, const char *name,
+                                    const void *buffer, size_t size, int flags)
 {
        return hfsplus_setxattr(dentry, name, buffer, size, flags,
                                XATTR_SECURITY_PREFIX,
                                XATTR_SECURITY_PREFIX_LEN);
 }
 
-static size_t hfsplus_security_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       /*
-        * This method is not used.
-        * It is used hfsplus_listxattr() instead of generic_listxattr().
-        */
-       return -EOPNOTSUPP;
-}
-
 static int hfsplus_initxattrs(struct inode *inode,
                                const struct xattr *xattr_array,
                                void *fs_info)
@@ -92,7 +84,6 @@ int hfsplus_init_inode_security(struct inode *inode,
 
 const struct xattr_handler hfsplus_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
-       .list   = hfsplus_security_listxattr,
        .get    = hfsplus_security_getxattr,
        .set    = hfsplus_security_setxattr,
 };
index bcf65089b7f7f11179d2304a9cee613664d8bd55..95a7704c7abb7b82358d5516c366ead6091d4fda 100644 (file)
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_trusted_getxattr(struct dentry *dentry, const char *name,
-                                       void *buffer, size_t size, int type)
+static int hfsplus_trusted_getxattr(const struct xattr_handler *handler,
+                                   struct dentry *dentry, const char *name,
+                                   void *buffer, size_t size)
 {
        return hfsplus_getxattr(dentry, name, buffer, size,
                                XATTR_TRUSTED_PREFIX,
                                XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static int hfsplus_trusted_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int hfsplus_trusted_setxattr(const struct xattr_handler *handler,
+                                   struct dentry *dentry, const char *name,
+                                   const void *buffer, size_t size, int flags)
 {
        return hfsplus_setxattr(dentry, name, buffer, size, flags,
                                XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static size_t hfsplus_trusted_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       /*
-        * This method is not used.
-        * It is used hfsplus_listxattr() instead of generic_listxattr().
-        */
-       return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_trusted_handler = {
        .prefix = XATTR_TRUSTED_PREFIX,
-       .list   = hfsplus_trusted_listxattr,
        .get    = hfsplus_trusted_getxattr,
        .set    = hfsplus_trusted_setxattr,
 };
index 5aa0e6dc4a1ee922edbde9ae440ea86572e17bc9..6fc269baf959a34bb9889b2be5c8a0711e895c94 100644 (file)
 #include "hfsplus_fs.h"
 #include "xattr.h"
 
-static int hfsplus_user_getxattr(struct dentry *dentry, const char *name,
-                                       void *buffer, size_t size, int type)
+static int hfsplus_user_getxattr(const struct xattr_handler *handler,
+                                struct dentry *dentry, const char *name,
+                                void *buffer, size_t size)
 {
 
        return hfsplus_getxattr(dentry, name, buffer, size,
                                XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static int hfsplus_user_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int hfsplus_user_setxattr(const struct xattr_handler *handler,
+                                struct dentry *dentry, const char *name,
+                                const void *buffer, size_t size, int flags)
 {
        return hfsplus_setxattr(dentry, name, buffer, size, flags,
                                XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 }
 
-static size_t hfsplus_user_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
-{
-       /*
-        * This method is not used.
-        * It is used hfsplus_listxattr() instead of generic_listxattr().
-        */
-       return -EOPNOTSUPP;
-}
-
 const struct xattr_handler hfsplus_xattr_user_handler = {
        .prefix = XATTR_USER_PREFIX,
-       .list   = hfsplus_user_listxattr,
        .get    = hfsplus_user_getxattr,
        .set    = hfsplus_user_setxattr,
 };
index 316adb968b6588faca5d64cf57005f48e067bb08..de4bdfac0cec36f7f3e1d5cee94ec4aecef3e311 100644 (file)
@@ -332,12 +332,17 @@ static void remove_huge_page(struct page *page)
  * truncation is indicated by end of range being LLONG_MAX
  *     In this case, we first scan the range and release found pages.
  *     After releasing pages, hugetlb_unreserve_pages cleans up region/reserv
- *     maps and global counts.
+ *     maps and global counts.  Page faults can not race with truncation
+ *     in this routine.  hugetlb_no_page() prevents page faults in the
+ *     truncated range.  It checks i_size before allocation, and again after
+ *     with the page table lock for the page held.  The same lock must be
+ *     acquired to unmap a page.
  * hole punch is indicated if end is not LLONG_MAX
  *     In the hole punch case we scan the range and release found pages.
  *     Only when releasing a page is the associated region/reserv map
  *     deleted.  The region/reserv map for ranges without associated
- *     pages are not modified.
+ *     pages are not modified.  Page faults can race with hole punch.
+ *     This is indicated if we find a mapped page.
  * Note: If the passed end of range value is beyond the end of file, but
  * not LLONG_MAX this routine still performs a hole punch operation.
  */
@@ -361,46 +366,37 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
        next = start;
        while (next < end) {
                /*
-                * Make sure to never grab more pages that we
-                * might possibly need.
+                * Don't grab more pages than the number left in the range.
                 */
                if (end - next < lookup_nr)
                        lookup_nr = end - next;
 
                /*
-                * This pagevec_lookup() may return pages past 'end',
-                * so we must check for page->index > end.
+                * When no more pages are found, we are done.
                 */
-               if (!pagevec_lookup(&pvec, mapping, next, lookup_nr)) {
-                       if (next == start)
-                               break;
-                       next = start;
-                       continue;
-               }
+               if (!pagevec_lookup(&pvec, mapping, next, lookup_nr))
+                       break;
 
                for (i = 0; i < pagevec_count(&pvec); ++i) {
                        struct page *page = pvec.pages[i];
                        u32 hash;
 
+                       /*
+                        * The page (index) could be beyond end.  This is
+                        * only possible in the punch hole case as end is
+                        * max page offset in the truncate case.
+                        */
+                       next = page->index;
+                       if (next >= end)
+                               break;
+
                        hash = hugetlb_fault_mutex_hash(h, current->mm,
                                                        &pseudo_vma,
                                                        mapping, next, 0);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
                        lock_page(page);
-                       if (page->index >= end) {
-                               unlock_page(page);
-                               mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                               next = end;     /* we are done */
-                               break;
-                       }
-
-                       /*
-                        * If page is mapped, it was faulted in after being
-                        * unmapped.  Do nothing in this race case.  In the
-                        * normal case page is not mapped.
-                        */
-                       if (!page_mapped(page)) {
+                       if (likely(!page_mapped(page))) {
                                bool rsv_on_error = !PagePrivate(page);
                                /*
                                 * We must free the huge page and remove
@@ -421,17 +417,23 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                                                hugetlb_fix_reserve_counts(
                                                        inode, rsv_on_error);
                                }
+                       } else {
+                               /*
+                                * If page is mapped, it was faulted in after
+                                * being unmapped.  It indicates a race between
+                                * hole punch and page fault.  Do nothing in
+                                * this case.  Getting here in a truncate
+                                * operation is a bug.
+                                */
+                               BUG_ON(truncate_op);
                        }
 
-                       if (page->index > next)
-                               next = page->index;
-
-                       ++next;
                        unlock_page(page);
-
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                }
+               ++next;
                huge_pagevec_release(&pvec);
+               cond_resched();
        }
 
        if (truncate_op)
@@ -647,9 +649,6 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
        if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size)
                i_size_write(inode, offset + len);
        inode->i_ctime = CURRENT_TIME;
-       spin_lock(&inode->i_lock);
-       inode->i_private = NULL;
-       spin_unlock(&inode->i_lock);
 out:
        mutex_unlock(&inode->i_mutex);
        return error;
index d4b43fb7adb18db678fc6bacf9cf9a0f3432af19..bf12fe5f83d7e66fa1cf34883539126f12cadfe0 100644 (file)
@@ -48,8 +48,9 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
-static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
-                                  void *buffer, size_t size, int type)
+static int jffs2_security_getxattr(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *name,
+                                  void *buffer, size_t size)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -58,8 +59,9 @@ static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size);
 }
 
-static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int jffs2_security_setxattr(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *name,
+                                  const void *buffer, size_t size, int flags)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -68,8 +70,10 @@ static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size, flags);
 }
 
-static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
+static size_t jffs2_security_listxattr(const struct xattr_handler *handler,
+                                      struct dentry *dentry, char *list,
+                                      size_t list_size, const char *name,
+                                      size_t name_len)
 {
        size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
 
index f092fee5be50511f643e9fac79c03d393cef18f2..4c2c03663533dc2fbf1e0c24dc5b08dec6ea943f 100644 (file)
@@ -1001,11 +1001,12 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
                if (!xhandle)
                        continue;
                if (buffer) {
-                       rc = xhandle->list(dentry, buffer+len, size-len,
-                                          xd->xname, xd->name_len, xd->flags);
+                       rc = xhandle->list(xhandle, dentry, buffer + len,
+                                          size - len, xd->xname,
+                                          xd->name_len);
                } else {
-                       rc = xhandle->list(dentry, NULL, 0, xd->xname,
-                                          xd->name_len, xd->flags);
+                       rc = xhandle->list(xhandle, dentry, NULL, 0,
+                                          xd->xname, xd->name_len);
                }
                if (rc < 0)
                        goto out;
index ceaf9c693225b44edeb5bb3bddea534c1b62ad51..a562da0d6a26186dc2116d6b8a05795903a46897 100644 (file)
@@ -16,8 +16,9 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
+                                 struct dentry *dentry, const char *name,
+                                 void *buffer, size_t size)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -25,8 +26,9 @@ static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size);
 }
 
-static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
+                                 struct dentry *dentry, const char *name,
+                                 const void *buffer, size_t size, int flags)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -34,11 +36,16 @@ static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size, flags);
 }
 
-static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
+static size_t jffs2_trusted_listxattr(const struct xattr_handler *handler,
+                                     struct dentry *dentry, char *list,
+                                     size_t list_size, const char *name,
+                                     size_t name_len)
 {
        size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return 0;
+
        if (list && retlen<=list_size) {
                strcpy(list, XATTR_TRUSTED_PREFIX);
                strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
index a71391eba51497bf7902f10ee44955e67b623e5e..cbc0472e59a8b01b81ea142f35d29c88c3a12c00 100644 (file)
@@ -16,8 +16,9 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
-                              void *buffer, size_t size, int type)
+static int jffs2_user_getxattr(const struct xattr_handler *handler,
+                              struct dentry *dentry, const char *name,
+                              void *buffer, size_t size)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -25,8 +26,9 @@ static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size);
 }
 
-static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
-               const void *buffer, size_t size, int flags, int type)
+static int jffs2_user_setxattr(const struct xattr_handler *handler,
+                              struct dentry *dentry, const char *name,
+                              const void *buffer, size_t size, int flags)
 {
        if (!strcmp(name, ""))
                return -EINVAL;
@@ -34,8 +36,10 @@ static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
                                 name, buffer, size, flags);
 }
 
-static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
-               size_t list_size, const char *name, size_t name_len, int type)
+static size_t jffs2_user_listxattr(const struct xattr_handler *handler,
+                                  struct dentry *dentry, char *list,
+                                  size_t list_size, const char *name,
+                                  size_t name_len)
 {
        size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
 
index 79b113048eacdc645fb67994cb0dcb25aad84dd0..0a3f9b594602341350afb79f27ba2cd8191468e8 100644 (file)
@@ -525,6 +525,8 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
                        switch (rqdata.cmd) {
                                case NCP_LOCK_EX:
                                case NCP_LOCK_SH:
+                                               if (rqdata.timeout < 0)
+                                                       return -EINVAL;
                                                if (rqdata.timeout == 0)
                                                        rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;
                                                else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT)
index 646cdac73488e96041f2bcad33b4220b096da684..beac58b0e09cbbb0a3cc74fbb55bfe6853c1d616 100644 (file)
@@ -78,7 +78,8 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes)
 
        p = xdr_inline_decode(xdr, nbytes);
        if (unlikely(p == NULL))
-               printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
+               printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed "
+                                                       "or truncated request.\n");
        return p;
 }
 
@@ -889,6 +890,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        struct cb_compound_hdr_arg hdr_arg = { 0 };
        struct cb_compound_hdr_res hdr_res = { NULL };
        struct xdr_stream xdr_in, xdr_out;
+       struct xdr_buf *rq_arg = &rqstp->rq_arg;
        __be32 *p, status;
        struct cb_process_state cps = {
                .drc_status = 0,
@@ -900,7 +902,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
 
        dprintk("%s: start\n", __func__);
 
-       xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
+       rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len;
+       xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base);
 
        p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
        xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
index 326d9e10d83370f56061220c51e72a42de0595b2..31b0a52223a73758c385d18bea4ec22ed63c2884 100644 (file)
@@ -618,7 +618,10 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
                nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
                nfs_vmtruncate(inode, attr->ia_size);
        }
-       nfs_update_inode(inode, fattr);
+       if (fattr->valid)
+               nfs_update_inode(inode, fattr);
+       else
+               NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
        spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
@@ -1824,7 +1827,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0)
                        nfsi->attr_gencount = fattr->gencount;
        }
-       invalid &= ~NFS_INO_INVALID_ATTR;
+
+       /* Don't declare attrcache up to date if there were no attrs! */
+       if (fattr->valid != 0)
+               invalid &= ~NFS_INO_INVALID_ATTR;
+
        /* Don't invalidate the data if we were to blame */
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
                                || S_ISLNK(inode->i_mode)))
index 3e92a3cde15d8b61878a7c2ce7d13da1cf01b290..6b1ce9825430c7c9659b49ac9bff545b620bd7bb 100644 (file)
@@ -14,7 +14,7 @@
 #include "pnfs.h"
 #include "internal.h"
 
-#define NFSDBG_FACILITY NFSDBG_PNFS
+#define NFSDBG_FACILITY NFSDBG_PROC
 
 static int nfs42_set_rw_stateid(nfs4_stateid *dst, struct file *file,
                                fmode_t fmode)
@@ -284,6 +284,7 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
                .dst_fh = NFS_FH(dst_inode),
                .src_offset = src_offset,
                .dst_offset = dst_offset,
+               .count = count,
                .dst_bitmask = server->cache_consistency_bitmask,
        };
        struct nfs42_clone_res res = {
index 223bedda64ae49f3d94226677e652e31da4c8d84..10410e8b58530389d7efb18352e8a6253d12b267 100644 (file)
@@ -33,7 +33,7 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)
                return ret;
        idr_preload(GFP_KERNEL);
        spin_lock(&nn->nfs_client_lock);
-       ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT);
+       ret = idr_alloc(&nn->cb_ident_idr, clp, 1, 0, GFP_NOWAIT);
        if (ret >= 0)
                clp->cl_cb_ident = ret;
        spin_unlock(&nn->nfs_client_lock);
index 4aa571956cd618499df260f6bcf6a0f7c2df8045..db9b5fea5b3ef12f6eacf36cd2154c2db7d4d9f2 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/file.h>
 #include <linux/falloc.h>
 #include <linux/nfs_fs.h>
+#include <uapi/linux/btrfs.h>  /* BTRFS_IOC_CLONE/BTRFS_IOC_CLONE_RANGE */
 #include "delegation.h"
 #include "internal.h"
 #include "iostat.h"
@@ -203,6 +204,7 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
        struct fd src_file;
        struct inode *src_inode;
        unsigned int bs = server->clone_blksize;
+       bool same_inode = false;
        int ret;
 
        /* dst file must be opened for writing */
@@ -221,10 +223,8 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
 
        src_inode = file_inode(src_file.file);
 
-       /* src and dst must be different files */
-       ret = -EINVAL;
        if (src_inode == dst_inode)
-               goto out_fput;
+               same_inode = true;
 
        /* src file must be opened for reading */
        if (!(src_file.file->f_mode & FMODE_READ))
@@ -249,8 +249,16 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
                        goto out_fput;
        }
 
+       /* verify if ranges are overlapped within the same file */
+       if (same_inode) {
+               if (dst_off + count > src_off && dst_off < src_off + count)
+                       goto out_fput;
+       }
+
        /* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */
-       if (dst_inode < src_inode) {
+       if (same_inode) {
+               mutex_lock(&src_inode->i_mutex);
+       } else if (dst_inode < src_inode) {
                mutex_lock_nested(&dst_inode->i_mutex, I_MUTEX_PARENT);
                mutex_lock_nested(&src_inode->i_mutex, I_MUTEX_CHILD);
        } else {
@@ -275,7 +283,9 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
                truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1);
 
 out_unlock:
-       if (dst_inode < src_inode) {
+       if (same_inode) {
+               mutex_unlock(&src_inode->i_mutex);
+       } else if (dst_inode < src_inode) {
                mutex_unlock(&src_inode->i_mutex);
                mutex_unlock(&dst_inode->i_mutex);
        } else {
@@ -291,46 +301,31 @@ nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
 
 static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp)
 {
-       struct nfs_ioctl_clone_range_args args;
+       struct btrfs_ioctl_clone_range_args args;
 
        if (copy_from_user(&args, argp, sizeof(args)))
                return -EFAULT;
 
-       return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_off, args.dst_off, args.count);
-}
-#else
-static long nfs42_ioctl_clone(struct file *dst_file, unsigned long srcfd,
-               u64 src_off, u64 dst_off, u64 count)
-{
-       return -ENOTTY;
-}
-
-static long nfs42_ioctl_clone_range(struct file *dst_file, void __user *argp)
-{
-       return -ENOTTY;
+       return nfs42_ioctl_clone(dst_file, args.src_fd, args.src_offset,
+                                args.dest_offset, args.src_length);
 }
-#endif /* CONFIG_NFS_V4_2 */
 
 long nfs4_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
 
        switch (cmd) {
-       case NFS_IOC_CLONE:
+       case BTRFS_IOC_CLONE:
                return nfs42_ioctl_clone(file, arg, 0, 0, 0);
-       case NFS_IOC_CLONE_RANGE:
+       case BTRFS_IOC_CLONE_RANGE:
                return nfs42_ioctl_clone_range(file, argp);
        }
 
        return -ENOTTY;
 }
+#endif /* CONFIG_NFS_V4_2 */
 
 const struct file_operations nfs4_file_operations = {
-#ifdef CONFIG_NFS_V4_2
-       .llseek         = nfs4_file_llseek,
-#else
-       .llseek         = nfs_file_llseek,
-#endif
        .read_iter      = nfs_file_read,
        .write_iter     = nfs_file_write,
        .mmap           = nfs_file_mmap,
@@ -342,14 +337,14 @@ const struct file_operations nfs4_file_operations = {
        .flock          = nfs_flock,
        .splice_read    = nfs_file_splice_read,
        .splice_write   = iter_file_splice_write,
-#ifdef CONFIG_NFS_V4_2
-       .fallocate      = nfs42_fallocate,
-#endif /* CONFIG_NFS_V4_2 */
        .check_flags    = nfs_check_flags,
        .setlease       = simple_nosetlease,
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_NFS_V4_2
+       .llseek         = nfs4_file_llseek,
+       .fallocate      = nfs42_fallocate,
        .unlocked_ioctl = nfs4_ioctl,
-#else
        .compat_ioctl   = nfs4_ioctl,
-#endif /* CONFIG_COMPAT */
+#else
+       .llseek         = nfs_file_llseek,
+#endif
 };
index ff5bddc49a2a30449a63a6c2a32a2aadc6db84b5..89818036f035b01eaaa4e45797205d53f48e9934 100644 (file)
@@ -6248,9 +6248,10 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
 
 #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
 
-static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
+static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *key,
                                   const void *buf, size_t buflen,
-                                  int flags, int type)
+                                  int flags)
 {
        if (strcmp(key, "") != 0)
                return -EINVAL;
@@ -6258,8 +6259,9 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
        return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
 }
 
-static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
-                                  void *buf, size_t buflen, int type)
+static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *key,
+                                  void *buf, size_t buflen)
 {
        if (strcmp(key, "") != 0)
                return -EINVAL;
@@ -6267,9 +6269,10 @@ static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
        return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
 }
 
-static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
+static size_t nfs4_xattr_list_nfs4_acl(const struct xattr_handler *handler,
+                                      struct dentry *dentry, char *list,
                                       size_t list_len, const char *name,
-                                      size_t name_len, int type)
+                                      size_t name_len)
 {
        size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
@@ -6287,9 +6290,10 @@ static inline int nfs4_server_supports_labels(struct nfs_server *server)
        return server->caps & NFS_CAP_SECURITY_LABEL;
 }
 
-static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
-                                  const void *buf, size_t buflen,
-                                  int flags, int type)
+static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
+                                    struct dentry *dentry, const char *key,
+                                    const void *buf, size_t buflen,
+                                    int flags)
 {
        if (security_ismaclabel(key))
                return nfs4_set_security_label(dentry, buf, buflen);
@@ -6297,17 +6301,19 @@ static int nfs4_xattr_set_nfs4_label(struct dentry *dentry, const char *key,
        return -EOPNOTSUPP;
 }
 
-static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
-                                  void *buf, size_t buflen, int type)
+static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
+                                    struct dentry *dentry, const char *key,
+                                    void *buf, size_t buflen)
 {
        if (security_ismaclabel(key))
                return nfs4_get_security_label(d_inode(dentry), buf, buflen);
        return -EOPNOTSUPP;
 }
 
-static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
-                                      size_t list_len, const char *name,
-                                      size_t name_len, int type)
+static size_t nfs4_xattr_list_nfs4_label(const struct xattr_handler *handler,
+                                        struct dentry *dentry, char *list,
+                                        size_t list_len, const char *name,
+                                        size_t name_len)
 {
        size_t len = 0;
 
@@ -7860,7 +7866,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
                        spin_unlock(&inode->i_lock);
                goto out_restart;
        }
-       if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN)
+       if (nfs4_async_handle_error(task, server, state, &lgp->timeout) == -EAGAIN)
                goto out_restart;
 out:
        dprintk("<-- %s\n", __func__);
index dfed4f5c8fccf91a91b5669461d4a3f490b12cb2..4e4441216804ec550f2c135ef0f393f4f7a1426c 100644 (file)
@@ -3615,6 +3615,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
        status = 0;
        if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
                goto out;
+       bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS;
        status = -EIO;
        /* Ignore borken servers that return unrequested attrs */
        if (unlikely(res == NULL))
index 93496c0598375409876f4a25f95d90ef7feb7334..5a8ae2125b50855d6f9f304ffd737fbbb57bb02a 100644 (file)
@@ -872,33 +872,38 @@ send_layoutget(struct pnfs_layout_hdr *lo,
 
        dprintk("--> %s\n", __func__);
 
-       lgp = kzalloc(sizeof(*lgp), gfp_flags);
-       if (lgp == NULL)
-               return NULL;
+       /*
+        * Synchronously retrieve layout information from server and
+        * store in lseg. If we race with a concurrent seqid morphing
+        * op, then re-send the LAYOUTGET.
+        */
+       do {
+               lgp = kzalloc(sizeof(*lgp), gfp_flags);
+               if (lgp == NULL)
+                       return NULL;
+
+               i_size = i_size_read(ino);
+
+               lgp->args.minlength = PAGE_CACHE_SIZE;
+               if (lgp->args.minlength > range->length)
+                       lgp->args.minlength = range->length;
+               if (range->iomode == IOMODE_READ) {
+                       if (range->offset >= i_size)
+                               lgp->args.minlength = 0;
+                       else if (i_size - range->offset < lgp->args.minlength)
+                               lgp->args.minlength = i_size - range->offset;
+               }
+               lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
+               lgp->args.range = *range;
+               lgp->args.type = server->pnfs_curr_ld->id;
+               lgp->args.inode = ino;
+               lgp->args.ctx = get_nfs_open_context(ctx);
+               lgp->gfp_flags = gfp_flags;
+               lgp->cred = lo->plh_lc_cred;
 
-       i_size = i_size_read(ino);
+               lseg = nfs4_proc_layoutget(lgp, gfp_flags);
+       } while (lseg == ERR_PTR(-EAGAIN));
 
-       lgp->args.minlength = PAGE_CACHE_SIZE;
-       if (lgp->args.minlength > range->length)
-               lgp->args.minlength = range->length;
-       if (range->iomode == IOMODE_READ) {
-               if (range->offset >= i_size)
-                       lgp->args.minlength = 0;
-               else if (i_size - range->offset < lgp->args.minlength)
-                       lgp->args.minlength = i_size - range->offset;
-       }
-       lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
-       lgp->args.range = *range;
-       lgp->args.type = server->pnfs_curr_ld->id;
-       lgp->args.inode = ino;
-       lgp->args.ctx = get_nfs_open_context(ctx);
-       lgp->gfp_flags = gfp_flags;
-       lgp->cred = lo->plh_lc_cred;
-
-       /* Synchronously retrieve layout information from server and
-        * store in lseg.
-        */
-       lseg = nfs4_proc_layoutget(lgp, gfp_flags);
        if (IS_ERR(lseg)) {
                switch (PTR_ERR(lseg)) {
                case -ENOMEM:
@@ -1687,6 +1692,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
                /* existing state ID, make sure the sequence number matches. */
                if (pnfs_layout_stateid_blocked(lo, &res->stateid)) {
                        dprintk("%s forget reply due to sequence\n", __func__);
+                       status = -EAGAIN;
                        goto out_forget_reply;
                }
                pnfs_set_layout_stateid(lo, &res->stateid, false);
index ddddef0021a0f8cd94f456969099bc660ec1fdb5..709fbbd44c65366ce1e31aebce0904b5966d53a6 100644 (file)
@@ -1480,16 +1480,17 @@ static int o2hb_read_block_input(struct o2hb_region *reg,
        return 0;
 }
 
-static ssize_t o2hb_region_block_bytes_read(struct o2hb_region *reg,
+static ssize_t o2hb_region_block_bytes_show(struct config_item *item,
                                            char *page)
 {
-       return sprintf(page, "%u\n", reg->hr_block_bytes);
+       return sprintf(page, "%u\n", to_o2hb_region(item)->hr_block_bytes);
 }
 
-static ssize_t o2hb_region_block_bytes_write(struct o2hb_region *reg,
+static ssize_t o2hb_region_block_bytes_store(struct config_item *item,
                                             const char *page,
                                             size_t count)
 {
+       struct o2hb_region *reg = to_o2hb_region(item);
        int status;
        unsigned long block_bytes;
        unsigned int block_bits;
@@ -1508,16 +1509,17 @@ static ssize_t o2hb_region_block_bytes_write(struct o2hb_region *reg,
        return count;
 }
 
-static ssize_t o2hb_region_start_block_read(struct o2hb_region *reg,
+static ssize_t o2hb_region_start_block_show(struct config_item *item,
                                            char *page)
 {
-       return sprintf(page, "%llu\n", reg->hr_start_block);
+       return sprintf(page, "%llu\n", to_o2hb_region(item)->hr_start_block);
 }
 
-static ssize_t o2hb_region_start_block_write(struct o2hb_region *reg,
+static ssize_t o2hb_region_start_block_store(struct config_item *item,
                                             const char *page,
                                             size_t count)
 {
+       struct o2hb_region *reg = to_o2hb_region(item);
        unsigned long long tmp;
        char *p = (char *)page;
 
@@ -1533,16 +1535,16 @@ static ssize_t o2hb_region_start_block_write(struct o2hb_region *reg,
        return count;
 }
 
-static ssize_t o2hb_region_blocks_read(struct o2hb_region *reg,
-                                      char *page)
+static ssize_t o2hb_region_blocks_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d\n", reg->hr_blocks);
+       return sprintf(page, "%d\n", to_o2hb_region(item)->hr_blocks);
 }
 
-static ssize_t o2hb_region_blocks_write(struct o2hb_region *reg,
+static ssize_t o2hb_region_blocks_store(struct config_item *item,
                                        const char *page,
                                        size_t count)
 {
+       struct o2hb_region *reg = to_o2hb_region(item);
        unsigned long tmp;
        char *p = (char *)page;
 
@@ -1561,13 +1563,12 @@ static ssize_t o2hb_region_blocks_write(struct o2hb_region *reg,
        return count;
 }
 
-static ssize_t o2hb_region_dev_read(struct o2hb_region *reg,
-                                   char *page)
+static ssize_t o2hb_region_dev_show(struct config_item *item, char *page)
 {
        unsigned int ret = 0;
 
-       if (reg->hr_bdev)
-               ret = sprintf(page, "%s\n", reg->hr_dev_name);
+       if (to_o2hb_region(item)->hr_bdev)
+               ret = sprintf(page, "%s\n", to_o2hb_region(item)->hr_dev_name);
 
        return ret;
 }
@@ -1677,10 +1678,11 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg)
 }
 
 /* this is acting as commit; we set up all of hr_bdev and hr_task or nothing */
-static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
+static ssize_t o2hb_region_dev_store(struct config_item *item,
                                     const char *page,
                                     size_t count)
 {
+       struct o2hb_region *reg = to_o2hb_region(item);
        struct task_struct *hb_task;
        long fd;
        int sectsize;
@@ -1841,9 +1843,9 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        return ret;
 }
 
-static ssize_t o2hb_region_pid_read(struct o2hb_region *reg,
-                                      char *page)
+static ssize_t o2hb_region_pid_show(struct config_item *item, char *page)
 {
+       struct o2hb_region *reg = to_o2hb_region(item);
        pid_t pid = 0;
 
        spin_lock(&o2hb_live_lock);
@@ -1857,92 +1859,23 @@ static ssize_t o2hb_region_pid_read(struct o2hb_region *reg,
        return sprintf(page, "%u\n", pid);
 }
 
-struct o2hb_region_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct o2hb_region *, char *);
-       ssize_t (*store)(struct o2hb_region *, const char *, size_t);
-};
-
-static struct o2hb_region_attribute o2hb_region_attr_block_bytes = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "block_bytes",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_region_block_bytes_read,
-       .store  = o2hb_region_block_bytes_write,
-};
-
-static struct o2hb_region_attribute o2hb_region_attr_start_block = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "start_block",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_region_start_block_read,
-       .store  = o2hb_region_start_block_write,
-};
-
-static struct o2hb_region_attribute o2hb_region_attr_blocks = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "blocks",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_region_blocks_read,
-       .store  = o2hb_region_blocks_write,
-};
-
-static struct o2hb_region_attribute o2hb_region_attr_dev = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "dev",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_region_dev_read,
-       .store  = o2hb_region_dev_write,
-};
-
-static struct o2hb_region_attribute o2hb_region_attr_pid = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "pid",
-                   .ca_mode = S_IRUGO | S_IRUSR },
-       .show   = o2hb_region_pid_read,
-};
+CONFIGFS_ATTR(o2hb_region_, block_bytes);
+CONFIGFS_ATTR(o2hb_region_, start_block);
+CONFIGFS_ATTR(o2hb_region_, blocks);
+CONFIGFS_ATTR(o2hb_region_, dev);
+CONFIGFS_ATTR_RO(o2hb_region_, pid);
 
 static struct configfs_attribute *o2hb_region_attrs[] = {
-       &o2hb_region_attr_block_bytes.attr,
-       &o2hb_region_attr_start_block.attr,
-       &o2hb_region_attr_blocks.attr,
-       &o2hb_region_attr_dev.attr,
-       &o2hb_region_attr_pid.attr,
+       &o2hb_region_attr_block_bytes,
+       &o2hb_region_attr_start_block,
+       &o2hb_region_attr_blocks,
+       &o2hb_region_attr_dev,
+       &o2hb_region_attr_pid,
        NULL,
 };
 
-static ssize_t o2hb_region_show(struct config_item *item,
-                               struct configfs_attribute *attr,
-                               char *page)
-{
-       struct o2hb_region *reg = to_o2hb_region(item);
-       struct o2hb_region_attribute *o2hb_region_attr =
-               container_of(attr, struct o2hb_region_attribute, attr);
-       ssize_t ret = 0;
-
-       if (o2hb_region_attr->show)
-               ret = o2hb_region_attr->show(reg, page);
-       return ret;
-}
-
-static ssize_t o2hb_region_store(struct config_item *item,
-                                struct configfs_attribute *attr,
-                                const char *page, size_t count)
-{
-       struct o2hb_region *reg = to_o2hb_region(item);
-       struct o2hb_region_attribute *o2hb_region_attr =
-               container_of(attr, struct o2hb_region_attribute, attr);
-       ssize_t ret = -EINVAL;
-
-       if (o2hb_region_attr->store)
-               ret = o2hb_region_attr->store(reg, page, count);
-       return ret;
-}
-
 static struct configfs_item_operations o2hb_region_item_ops = {
        .release                = o2hb_region_release,
-       .show_attribute         = o2hb_region_show,
-       .store_attribute        = o2hb_region_store,
 };
 
 static struct config_item_type o2hb_region_type = {
@@ -2137,49 +2070,14 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        spin_unlock(&o2hb_live_lock);
 }
 
-struct o2hb_heartbeat_group_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct o2hb_heartbeat_group *, char *);
-       ssize_t (*store)(struct o2hb_heartbeat_group *, const char *, size_t);
-};
-
-static ssize_t o2hb_heartbeat_group_show(struct config_item *item,
-                                        struct configfs_attribute *attr,
-                                        char *page)
-{
-       struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item));
-       struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr =
-               container_of(attr, struct o2hb_heartbeat_group_attribute, attr);
-       ssize_t ret = 0;
-
-       if (o2hb_heartbeat_group_attr->show)
-               ret = o2hb_heartbeat_group_attr->show(reg, page);
-       return ret;
-}
-
-static ssize_t o2hb_heartbeat_group_store(struct config_item *item,
-                                         struct configfs_attribute *attr,
-                                         const char *page, size_t count)
-{
-       struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item));
-       struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr =
-               container_of(attr, struct o2hb_heartbeat_group_attribute, attr);
-       ssize_t ret = -EINVAL;
-
-       if (o2hb_heartbeat_group_attr->store)
-               ret = o2hb_heartbeat_group_attr->store(reg, page, count);
-       return ret;
-}
-
-static ssize_t o2hb_heartbeat_group_threshold_show(struct o2hb_heartbeat_group *group,
-                                                    char *page)
+static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "%u\n", o2hb_dead_threshold);
 }
 
-static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group *group,
-                                                   const char *page,
-                                                   size_t count)
+static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item,
+               const char *page, size_t count)
 {
        unsigned long tmp;
        char *p = (char *)page;
@@ -2194,17 +2092,15 @@ static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group
        return count;
 }
 
-static
-ssize_t o2hb_heartbeat_group_mode_show(struct o2hb_heartbeat_group *group,
-                                      char *page)
+static ssize_t o2hb_heartbeat_group_mode_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page, "%s\n",
                       o2hb_heartbeat_mode_desc[o2hb_heartbeat_mode]);
 }
 
-static
-ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
-                                       const char *page, size_t count)
+static ssize_t o2hb_heartbeat_group_mode_store(struct config_item *item,
+               const char *page, size_t count)
 {
        unsigned int i;
        int ret;
@@ -2229,33 +2125,15 @@ ssize_t o2hb_heartbeat_group_mode_store(struct o2hb_heartbeat_group *group,
 
 }
 
-static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "dead_threshold",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_heartbeat_group_threshold_show,
-       .store  = o2hb_heartbeat_group_threshold_store,
-};
-
-static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_mode = {
-       .attr   = { .ca_owner = THIS_MODULE,
-               .ca_name = "mode",
-               .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2hb_heartbeat_group_mode_show,
-       .store  = o2hb_heartbeat_group_mode_store,
-};
+CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold);
+CONFIGFS_ATTR(o2hb_heartbeat_group_, mode);
 
 static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
-       &o2hb_heartbeat_group_attr_threshold.attr,
-       &o2hb_heartbeat_group_attr_mode.attr,
+       &o2hb_heartbeat_group_attr_threshold,
+       &o2hb_heartbeat_group_attr_mode,
        NULL,
 };
 
-static struct configfs_item_operations o2hb_heartbeat_group_item_ops = {
-       .show_attribute         = o2hb_heartbeat_group_show,
-       .store_attribute        = o2hb_heartbeat_group_store,
-};
-
 static struct configfs_group_operations o2hb_heartbeat_group_group_ops = {
        .make_item      = o2hb_heartbeat_group_make_item,
        .drop_item      = o2hb_heartbeat_group_drop_item,
@@ -2263,7 +2141,6 @@ static struct configfs_group_operations o2hb_heartbeat_group_group_ops = {
 
 static struct config_item_type o2hb_heartbeat_group_type = {
        .ct_group_ops   = &o2hb_heartbeat_group_group_ops,
-       .ct_item_ops    = &o2hb_heartbeat_group_item_ops,
        .ct_attrs       = o2hb_heartbeat_group_attrs,
        .ct_owner       = THIS_MODULE,
 };
index 441c84e169e6f05e819d7331027f6e519d02b3be..72afdca3cea70cbf87e2720e99dbff510be535f9 100644 (file)
@@ -172,9 +172,9 @@ static void o2nm_node_release(struct config_item *item)
        kfree(node);
 }
 
-static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page)
+static ssize_t o2nm_node_num_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d\n", node->nd_num);
+       return sprintf(page, "%d\n", to_o2nm_node(item)->nd_num);
 }
 
 static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
@@ -188,15 +188,16 @@ enum {
        O2NM_NODE_ATTR_NUM = 0,
        O2NM_NODE_ATTR_PORT,
        O2NM_NODE_ATTR_ADDRESS,
-       O2NM_NODE_ATTR_LOCAL,
 };
 
-static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
+static ssize_t o2nm_node_num_store(struct config_item *item, const char *page,
                                   size_t count)
 {
+       struct o2nm_node *node = to_o2nm_node(item);
        struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
        unsigned long tmp;
        char *p = (char *)page;
+       int ret = 0;
 
        tmp = simple_strtoul(p, &p, 0);
        if (!p || (*p && (*p != '\n')))
@@ -215,26 +216,30 @@ static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
 
        write_lock(&cluster->cl_nodes_lock);
        if (cluster->cl_nodes[tmp])
-               p = NULL;
+               ret = -EEXIST;
+       else if (test_and_set_bit(O2NM_NODE_ATTR_NUM,
+                       &node->nd_set_attributes))
+               ret = -EBUSY;
        else  {
                cluster->cl_nodes[tmp] = node;
                node->nd_num = tmp;
                set_bit(tmp, cluster->cl_nodes_bitmap);
        }
        write_unlock(&cluster->cl_nodes_lock);
-       if (p == NULL)
-               return -EEXIST;
+       if (ret)
+               return ret;
 
        return count;
 }
-static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page)
+static ssize_t o2nm_node_ipv4_port_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port));
+       return sprintf(page, "%u\n", ntohs(to_o2nm_node(item)->nd_ipv4_port));
 }
 
-static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
+static ssize_t o2nm_node_ipv4_port_store(struct config_item *item,
                                         const char *page, size_t count)
 {
+       struct o2nm_node *node = to_o2nm_node(item);
        unsigned long tmp;
        char *p = (char *)page;
 
@@ -247,20 +252,23 @@ static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
        if (tmp >= (u16)-1)
                return -ERANGE;
 
+       if (test_and_set_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
+               return -EBUSY;
        node->nd_ipv4_port = htons(tmp);
 
        return count;
 }
 
-static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page)
+static ssize_t o2nm_node_ipv4_address_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%pI4\n", &node->nd_ipv4_address);
+       return sprintf(page, "%pI4\n", &to_o2nm_node(item)->nd_ipv4_address);
 }
 
-static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
+static ssize_t o2nm_node_ipv4_address_store(struct config_item *item,
                                            const char *page,
                                            size_t count)
 {
+       struct o2nm_node *node = to_o2nm_node(item);
        struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
        int ret, i;
        struct rb_node **p, *parent;
@@ -282,6 +290,9 @@ static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
        write_lock(&cluster->cl_nodes_lock);
        if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
                ret = -EEXIST;
+       else if (test_and_set_bit(O2NM_NODE_ATTR_ADDRESS,
+                       &node->nd_set_attributes))
+               ret = -EBUSY;
        else {
                rb_link_node(&node->nd_ip_node, parent, p);
                rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
@@ -295,14 +306,15 @@ static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
        return count;
 }
 
-static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page)
+static ssize_t o2nm_node_local_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d\n", node->nd_local);
+       return sprintf(page, "%d\n", to_o2nm_node(item)->nd_local);
 }
 
-static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page,
+static ssize_t o2nm_node_local_store(struct config_item *item, const char *page,
                                     size_t count)
 {
+       struct o2nm_node *node = to_o2nm_node(item);
        struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
        unsigned long tmp;
        char *p = (char *)page;
@@ -349,108 +361,21 @@ static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page,
        return count;
 }
 
-struct o2nm_node_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct o2nm_node *, char *);
-       ssize_t (*store)(struct o2nm_node *, const char *, size_t);
-};
-
-static struct o2nm_node_attribute o2nm_node_attr_num = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "num",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_node_num_read,
-       .store  = o2nm_node_num_write,
-};
-
-static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "ipv4_port",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_node_ipv4_port_read,
-       .store  = o2nm_node_ipv4_port_write,
-};
-
-static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "ipv4_address",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_node_ipv4_address_read,
-       .store  = o2nm_node_ipv4_address_write,
-};
-
-static struct o2nm_node_attribute o2nm_node_attr_local = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "local",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_node_local_read,
-       .store  = o2nm_node_local_write,
-};
+CONFIGFS_ATTR(o2nm_node_, num);
+CONFIGFS_ATTR(o2nm_node_, ipv4_port);
+CONFIGFS_ATTR(o2nm_node_, ipv4_address);
+CONFIGFS_ATTR(o2nm_node_, local);
 
 static struct configfs_attribute *o2nm_node_attrs[] = {
-       [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr,
-       [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr,
-       [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr,
-       [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr,
+       &o2nm_node_attr_num,
+       &o2nm_node_attr_ipv4_port,
+       &o2nm_node_attr_ipv4_address,
+       &o2nm_node_attr_local,
        NULL,
 };
 
-static int o2nm_attr_index(struct configfs_attribute *attr)
-{
-       int i;
-       for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) {
-               if (attr == o2nm_node_attrs[i])
-                       return i;
-       }
-       BUG();
-       return 0;
-}
-
-static ssize_t o2nm_node_show(struct config_item *item,
-                             struct configfs_attribute *attr,
-                             char *page)
-{
-       struct o2nm_node *node = to_o2nm_node(item);
-       struct o2nm_node_attribute *o2nm_node_attr =
-               container_of(attr, struct o2nm_node_attribute, attr);
-       ssize_t ret = 0;
-
-       if (o2nm_node_attr->show)
-               ret = o2nm_node_attr->show(node, page);
-       return ret;
-}
-
-static ssize_t o2nm_node_store(struct config_item *item,
-                              struct configfs_attribute *attr,
-                              const char *page, size_t count)
-{
-       struct o2nm_node *node = to_o2nm_node(item);
-       struct o2nm_node_attribute *o2nm_node_attr =
-               container_of(attr, struct o2nm_node_attribute, attr);
-       ssize_t ret;
-       int attr_index = o2nm_attr_index(attr);
-
-       if (o2nm_node_attr->store == NULL) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (test_bit(attr_index, &node->nd_set_attributes))
-               return -EBUSY;
-
-       ret = o2nm_node_attr->store(node, page, count);
-       if (ret < count)
-               goto out;
-
-       set_bit(attr_index, &node->nd_set_attributes);
-out:
-       return ret;
-}
-
 static struct configfs_item_operations o2nm_node_item_ops = {
        .release                = o2nm_node_release,
-       .show_attribute         = o2nm_node_show,
-       .store_attribute        = o2nm_node_store,
 };
 
 static struct config_item_type o2nm_node_type = {
@@ -475,12 +400,6 @@ static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
 }
 #endif
 
-struct o2nm_cluster_attribute {
-       struct configfs_attribute attr;
-       ssize_t (*show)(struct o2nm_cluster *, char *);
-       ssize_t (*store)(struct o2nm_cluster *, const char *, size_t);
-};
-
 static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
                                        unsigned int *val)
 {
@@ -501,15 +420,16 @@ static ssize_t o2nm_cluster_attr_write(const char *page, ssize_t count,
        return count;
 }
 
-static ssize_t o2nm_cluster_attr_idle_timeout_ms_read(
-       struct o2nm_cluster *cluster, char *page)
+static ssize_t o2nm_cluster_idle_timeout_ms_show(struct config_item *item,
+       char *page)
 {
-       return sprintf(page, "%u\n", cluster->cl_idle_timeout_ms);
+       return sprintf(page, "%u\n", to_o2nm_cluster(item)->cl_idle_timeout_ms);
 }
 
-static ssize_t o2nm_cluster_attr_idle_timeout_ms_write(
-       struct o2nm_cluster *cluster, const char *page, size_t count)
+static ssize_t o2nm_cluster_idle_timeout_ms_store(struct config_item *item,
+       const char *page, size_t count)
 {
+       struct o2nm_cluster *cluster = to_o2nm_cluster(item);
        ssize_t ret;
        unsigned int val;
 
@@ -536,15 +456,17 @@ static ssize_t o2nm_cluster_attr_idle_timeout_ms_write(
        return ret;
 }
 
-static ssize_t o2nm_cluster_attr_keepalive_delay_ms_read(
-       struct o2nm_cluster *cluster, char *page)
+static ssize_t o2nm_cluster_keepalive_delay_ms_show(
+       struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", cluster->cl_keepalive_delay_ms);
+       return sprintf(page, "%u\n",
+                       to_o2nm_cluster(item)->cl_keepalive_delay_ms);
 }
 
-static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write(
-       struct o2nm_cluster *cluster, const char *page, size_t count)
+static ssize_t o2nm_cluster_keepalive_delay_ms_store(
+       struct config_item *item, const char *page, size_t count)
 {
+       struct o2nm_cluster *cluster = to_o2nm_cluster(item);
        ssize_t ret;
        unsigned int val;
 
@@ -571,22 +493,24 @@ static ssize_t o2nm_cluster_attr_keepalive_delay_ms_write(
        return ret;
 }
 
-static ssize_t o2nm_cluster_attr_reconnect_delay_ms_read(
-       struct o2nm_cluster *cluster, char *page)
+static ssize_t o2nm_cluster_reconnect_delay_ms_show(
+       struct config_item *item, char *page)
 {
-       return sprintf(page, "%u\n", cluster->cl_reconnect_delay_ms);
+       return sprintf(page, "%u\n",
+                       to_o2nm_cluster(item)->cl_reconnect_delay_ms);
 }
 
-static ssize_t o2nm_cluster_attr_reconnect_delay_ms_write(
-       struct o2nm_cluster *cluster, const char *page, size_t count)
+static ssize_t o2nm_cluster_reconnect_delay_ms_store(
+       struct config_item *item, const char *page, size_t count)
 {
        return o2nm_cluster_attr_write(page, count,
-                                      &cluster->cl_reconnect_delay_ms);
+                               &to_o2nm_cluster(item)->cl_reconnect_delay_ms);
 }
 
-static ssize_t o2nm_cluster_attr_fence_method_read(
-       struct o2nm_cluster *cluster, char *page)
+static ssize_t o2nm_cluster_fence_method_show(
+       struct config_item *item, char *page)
 {
+       struct o2nm_cluster *cluster = to_o2nm_cluster(item);
        ssize_t ret = 0;
 
        if (cluster)
@@ -595,8 +519,8 @@ static ssize_t o2nm_cluster_attr_fence_method_read(
        return ret;
 }
 
-static ssize_t o2nm_cluster_attr_fence_method_write(
-       struct o2nm_cluster *cluster, const char *page, size_t count)
+static ssize_t o2nm_cluster_fence_method_store(
+       struct config_item *item, const char *page, size_t count)
 {
        unsigned int i;
 
@@ -608,10 +532,10 @@ static ssize_t o2nm_cluster_attr_fence_method_write(
                        continue;
                if (strncasecmp(page, o2nm_fence_method_desc[i], count - 1))
                        continue;
-               if (cluster->cl_fence_method != i) {
+               if (to_o2nm_cluster(item)->cl_fence_method != i) {
                        printk(KERN_INFO "ocfs2: Changing fence method to %s\n",
                               o2nm_fence_method_desc[i]);
-                       cluster->cl_fence_method = i;
+                       to_o2nm_cluster(item)->cl_fence_method = i;
                }
                return count;
        }
@@ -620,79 +544,18 @@ static ssize_t o2nm_cluster_attr_fence_method_write(
        return -EINVAL;
 }
 
-static struct o2nm_cluster_attribute o2nm_cluster_attr_idle_timeout_ms = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "idle_timeout_ms",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_cluster_attr_idle_timeout_ms_read,
-       .store  = o2nm_cluster_attr_idle_timeout_ms_write,
-};
-
-static struct o2nm_cluster_attribute o2nm_cluster_attr_keepalive_delay_ms = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "keepalive_delay_ms",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_cluster_attr_keepalive_delay_ms_read,
-       .store  = o2nm_cluster_attr_keepalive_delay_ms_write,
-};
-
-static struct o2nm_cluster_attribute o2nm_cluster_attr_reconnect_delay_ms = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "reconnect_delay_ms",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_cluster_attr_reconnect_delay_ms_read,
-       .store  = o2nm_cluster_attr_reconnect_delay_ms_write,
-};
-
-static struct o2nm_cluster_attribute o2nm_cluster_attr_fence_method = {
-       .attr   = { .ca_owner = THIS_MODULE,
-                   .ca_name = "fence_method",
-                   .ca_mode = S_IRUGO | S_IWUSR },
-       .show   = o2nm_cluster_attr_fence_method_read,
-       .store  = o2nm_cluster_attr_fence_method_write,
-};
+CONFIGFS_ATTR(o2nm_cluster_, idle_timeout_ms);
+CONFIGFS_ATTR(o2nm_cluster_, keepalive_delay_ms);
+CONFIGFS_ATTR(o2nm_cluster_, reconnect_delay_ms);
+CONFIGFS_ATTR(o2nm_cluster_, fence_method);
 
 static struct configfs_attribute *o2nm_cluster_attrs[] = {
-       &o2nm_cluster_attr_idle_timeout_ms.attr,
-       &o2nm_cluster_attr_keepalive_delay_ms.attr,
-       &o2nm_cluster_attr_reconnect_delay_ms.attr,
-       &o2nm_cluster_attr_fence_method.attr,
+       &o2nm_cluster_attr_idle_timeout_ms,
+       &o2nm_cluster_attr_keepalive_delay_ms,
+       &o2nm_cluster_attr_reconnect_delay_ms,
+       &o2nm_cluster_attr_fence_method,
        NULL,
 };
-static ssize_t o2nm_cluster_show(struct config_item *item,
-                                 struct configfs_attribute *attr,
-                                 char *page)
-{
-       struct o2nm_cluster *cluster = to_o2nm_cluster(item);
-       struct o2nm_cluster_attribute *o2nm_cluster_attr =
-               container_of(attr, struct o2nm_cluster_attribute, attr);
-       ssize_t ret = 0;
-
-       if (o2nm_cluster_attr->show)
-               ret = o2nm_cluster_attr->show(cluster, page);
-       return ret;
-}
-
-static ssize_t o2nm_cluster_store(struct config_item *item,
-                                  struct configfs_attribute *attr,
-                                  const char *page, size_t count)
-{
-       struct o2nm_cluster *cluster = to_o2nm_cluster(item);
-       struct o2nm_cluster_attribute *o2nm_cluster_attr =
-               container_of(attr, struct o2nm_cluster_attribute, attr);
-       ssize_t ret;
-
-       if (o2nm_cluster_attr->store == NULL) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = o2nm_cluster_attr->store(cluster, page, count);
-       if (ret < count)
-               goto out;
-out:
-       return ret;
-}
 
 static struct config_item *o2nm_node_group_make_item(struct config_group *group,
                                                     const char *name)
@@ -773,8 +636,6 @@ static void o2nm_cluster_release(struct config_item *item)
 
 static struct configfs_item_operations o2nm_cluster_item_ops = {
        .release        = o2nm_cluster_release,
-       .show_attribute         = o2nm_cluster_show,
-       .store_attribute        = o2nm_cluster_store,
 };
 
 static struct config_item_type o2nm_cluster_type = {
index 3b48ac25d8a7c450ac23360b5f7d28e9fafcc263..a03f6f433075c02d3c87c192b362d2c7f2e96952 100644 (file)
@@ -372,6 +372,8 @@ static int ocfs2_mknod(struct inode *dir,
                mlog_errno(status);
                goto leave;
        }
+       /* update inode->i_mode after mask with "umask". */
+       inode->i_mode = mode;
 
        handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
                                                            S_ISDIR(mode),
index ebfdea78659b1bda5a93674837e8f818c2503d44..e9164f09841bfd6bc3f5baf439b91f8dfe5345f2 100644 (file)
@@ -7229,9 +7229,10 @@ int ocfs2_init_security_and_acl(struct inode *dir,
 /*
  * 'security' attributes support
  */
-static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_security_list(const struct xattr_handler *handler,
+                                       struct dentry *dentry, char *list,
                                        size_t list_size, const char *name,
-                                       size_t name_len, int type)
+                                       size_t name_len)
 {
        const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -7244,8 +7245,9 @@ static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
-                                   void *buffer, size_t size, int type)
+static int ocfs2_xattr_security_get(const struct xattr_handler *handler,
+                                   struct dentry *dentry, const char *name,
+                                   void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -7253,8 +7255,9 @@ static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
                               name, buffer, size);
 }
 
-static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int ocfs2_xattr_security_set(const struct xattr_handler *handler,
+                                   struct dentry *dentry, const char *name,
+                                   const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -7319,9 +7322,10 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
 /*
  * 'trusted' attributes support
  */
-static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_trusted_list(const struct xattr_handler *handler,
+                                      struct dentry *dentry, char *list,
                                       size_t list_size, const char *name,
-                                      size_t name_len, int type)
+                                      size_t name_len)
 {
        const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -7337,8 +7341,9 @@ static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *name,
+                                  void *buffer, size_t size)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -7346,8 +7351,9 @@ static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
                               name, buffer, size);
 }
 
-static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler,
+                                  struct dentry *dentry, const char *name,
+                                  const void *value, size_t size, int flags)
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -7366,9 +7372,10 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
 /*
  * 'user' attributes support
  */
-static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
+static size_t ocfs2_xattr_user_list(const struct xattr_handler *handler,
+                                   struct dentry *dentry, char *list,
                                    size_t list_size, const char *name,
-                                   size_t name_len, int type)
+                                   size_t name_len)
 {
        const size_t prefix_len = XATTR_USER_PREFIX_LEN;
        const size_t total_len = prefix_len + name_len + 1;
@@ -7385,8 +7392,9 @@ static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
        return total_len;
 }
 
-static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
-               void *buffer, size_t size, int type)
+static int ocfs2_xattr_user_get(const struct xattr_handler *handler,
+                               struct dentry *dentry, const char *name,
+                               void *buffer, size_t size)
 {
        struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
@@ -7398,8 +7406,9 @@ static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
                               buffer, size);
 }
 
-static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+static int ocfs2_xattr_user_set(const struct xattr_handler *handler,
+                               struct dentry *dentry, const char *name,
+                               const void *value, size_t size, int flags)
 {
        struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
index 4fb17ded7d4780d8d19e7c68cb1c7cedfeb79cf7..4adde1e2cbece693ebab67527a555e3a33e6fbfa 100644 (file)
@@ -762,18 +762,21 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
 EXPORT_SYMBOL (posix_acl_to_xattr);
 
 static int
-posix_acl_xattr_get(struct dentry *dentry, const char *name,
-               void *value, size_t size, int type)
+posix_acl_xattr_get(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   void *value, size_t size)
 {
        struct posix_acl *acl;
        int error;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!IS_POSIXACL(d_backing_inode(dentry)))
                return -EOPNOTSUPP;
        if (d_is_symlink(dentry))
                return -EOPNOTSUPP;
 
-       acl = get_acl(d_backing_inode(dentry), type);
+       acl = get_acl(d_backing_inode(dentry), handler->flags);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -786,19 +789,22 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
 }
 
 static int
-posix_acl_xattr_set(struct dentry *dentry, const char *name,
-               const void *value, size_t size, int flags, int type)
+posix_acl_xattr_set(const struct xattr_handler *handler,
+                   struct dentry *dentry, const char *name,
+                   const void *value, size_t size, int flags)
 {
        struct inode *inode = d_backing_inode(dentry);
        struct posix_acl *acl = NULL;
        int ret;
 
+       if (strcmp(name, "") != 0)
+               return -EINVAL;
        if (!IS_POSIXACL(inode))
                return -EOPNOTSUPP;
        if (!inode->i_op->set_acl)
                return -EOPNOTSUPP;
 
-       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+       if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
                return value ? -EACCES : 0;
        if (!inode_owner_or_capable(inode))
                return -EPERM;
@@ -815,28 +821,22 @@ posix_acl_xattr_set(struct dentry *dentry, const char *name,
                }
        }
 
-       ret = inode->i_op->set_acl(inode, acl, type);
+       ret = inode->i_op->set_acl(inode, acl, handler->flags);
 out:
        posix_acl_release(acl);
        return ret;
 }
 
 static size_t
-posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
-               const char *name, size_t name_len, int type)
+posix_acl_xattr_list(const struct xattr_handler *handler,
+                    struct dentry *dentry, char *list, size_t list_size,
+                    const char *name, size_t name_len)
 {
-       const char *xname;
+       const char *xname = handler->prefix;
        size_t size;
 
        if (!IS_POSIXACL(d_backing_inode(dentry)))
-               return -EOPNOTSUPP;
-       if (d_is_symlink(dentry))
-               return -EOPNOTSUPP;
-
-       if (type == ACL_TYPE_ACCESS)
-               xname = POSIX_ACL_XATTR_ACCESS;
-       else
-               xname = POSIX_ACL_XATTR_DEFAULT;
+               return 0;
 
        size = strlen(xname) + 1;
        if (list && size <= list_size)
index e87f9b52bf069af087979782767b6c3471689fd5..66b26fdfff8d6de51082b48b0f9a61fba9567466 100644 (file)
@@ -778,7 +778,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
        if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->get(dentry, name, buffer, size, handler->flags);
+       return handler->get(handler, dentry, name, buffer, size);
 }
 
 /*
@@ -797,7 +797,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->set(dentry, name, value, size, flags, handler->flags);
+       return handler->set(handler, dentry, name, value, size, flags);
 }
 
 /*
@@ -814,7 +814,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
        if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
+       return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE);
 }
 
 struct listxattr_buf {
@@ -842,14 +842,14 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
                if (!handler)   /* Unsupported xattr name */
                        return 0;
                if (b->buf) {
-                       size = handler->list(b->dentry, b->buf + b->pos,
-                                        b->size, name, namelen,
-                                        handler->flags);
+                       size = handler->list(handler, b->dentry,
+                                            b->buf + b->pos, b->size, name,
+                                            namelen);
                        if (size > b->size)
                                return -ERANGE;
                } else {
-                       size = handler->list(b->dentry, NULL, 0, name,
-                                            namelen, handler->flags);
+                       size = handler->list(handler, b->dentry,
+                                            NULL, 0, name, namelen);
                }
 
                b->pos += size;
index 9a3b0616f2838848c88dbf90497ebb9af0a68e2a..ac659af431aec83d5ba7b85e7b69c1ac49e7b4c0 100644 (file)
@@ -9,8 +9,8 @@
 #include <linux/uaccess.h>
 
 static int
-security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-               int handler_flags)
+security_get(const struct xattr_handler *handler, struct dentry *dentry,
+            const char *name, void *buffer, size_t size)
 {
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
@@ -22,8 +22,8 @@ security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 }
 
 static int
-security_set(struct dentry *dentry, const char *name, const void *buffer,
-            size_t size, int flags, int handler_flags)
+security_set(const struct xattr_handler *handler, struct dentry *dentry,
+            const char *name, const void *buffer, size_t size, int flags)
 {
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
@@ -34,8 +34,9 @@ security_set(struct dentry *dentry, const char *name, const void *buffer,
        return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
-                           const char *name, size_t namelen, int handler_flags)
+static size_t security_list(const struct xattr_handler *handler,
+                           struct dentry *dentry, char *list, size_t list_len,
+                           const char *name, size_t namelen)
 {
        const size_t len = namelen + 1;
 
index e4f1343714e0ea8a89598bb776dc8a3f6b42c67d..a338adf1b8b4816c19ca84557a0142179f93b9a7 100644 (file)
@@ -8,8 +8,8 @@
 #include <linux/uaccess.h>
 
 static int
-trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-           int handler_flags)
+trusted_get(const struct xattr_handler *handler, struct dentry *dentry,
+           const char *name, void *buffer, size_t size)
 {
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
@@ -21,8 +21,8 @@ trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 }
 
 static int
-trusted_set(struct dentry *dentry, const char *name, const void *buffer,
-           size_t size, int flags, int handler_flags)
+trusted_set(const struct xattr_handler *handler, struct dentry *dentry,
+           const char *name, const void *buffer, size_t size, int flags)
 {
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
@@ -33,8 +33,9 @@ trusted_set(struct dentry *dentry, const char *name, const void *buffer,
        return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
-                          const char *name, size_t name_len, int handler_flags)
+static size_t trusted_list(const struct xattr_handler *handler,
+                          struct dentry *dentry, char *list, size_t list_size,
+                          const char *name, size_t name_len)
 {
        const size_t len = name_len + 1;
 
index d0b08d3e5689d39aeffbd1d86e13711b50e56f22..39c9667191c5db5b3c930e538d81799b96bea6fb 100644 (file)
@@ -7,8 +7,8 @@
 #include <linux/uaccess.h>
 
 static int
-user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
-        int handler_flags)
+user_get(const struct xattr_handler *handler, struct dentry *dentry,
+        const char *name, void *buffer, size_t size)
 {
 
        if (strlen(name) < sizeof(XATTR_USER_PREFIX))
@@ -19,8 +19,8 @@ user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
 }
 
 static int
-user_set(struct dentry *dentry, const char *name, const void *buffer,
-        size_t size, int flags, int handler_flags)
+user_set(const struct xattr_handler *handler, struct dentry *dentry,
+        const char *name, const void *buffer, size_t size, int flags)
 {
        if (strlen(name) < sizeof(XATTR_USER_PREFIX))
                return -EINVAL;
@@ -30,8 +30,9 @@ user_set(struct dentry *dentry, const char *name, const void *buffer,
        return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
-static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
-                       const char *name, size_t name_len, int handler_flags)
+static size_t user_list(const struct xattr_handler *handler,
+                       struct dentry *dentry, char *list, size_t list_size,
+                       const char *name, size_t name_len)
 {
        const size_t len = name_len + 1;
 
index 801c21cd77fe4f1d344aed6fa7b28369972d82b2..4cf700d50b4037e6c334b0647cdb81b816f9ef65 100644 (file)
@@ -809,6 +809,13 @@ static int splice_from_pipe_feed(struct pipe_inode_info *pipe, struct splice_des
  */
 static int splice_from_pipe_next(struct pipe_inode_info *pipe, struct splice_desc *sd)
 {
+       /*
+        * Check for signal early to make process killable when there are
+        * always buffers available
+        */
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
        while (!pipe->nrbufs) {
                if (!pipe->writers)
                        return 0;
@@ -884,6 +891,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
 
        splice_from_pipe_begin(sd);
        do {
+               cond_resched();
                ret = splice_from_pipe_next(pipe, sd);
                if (ret > 0)
                        ret = splice_from_pipe_feed(pipe, sd, actor);
index e5e0ddf5b1430d335075220824897c2e38d1b289..6a4cc344085c0a9ecb3ce4106b168172739dd161 100644 (file)
@@ -68,8 +68,8 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
                name_size = le16_to_cpu(entry.size);
                handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
                if (handler)
-                       prefix_size = handler->list(d, buffer, rest, NULL,
-                               name_size, handler->flags);
+                       prefix_size = handler->list(handler, d, buffer, rest,
+                                                   NULL, name_size);
                if (prefix_size) {
                        if (buffer) {
                                if (prefix_size + name_size + 1 > rest) {
@@ -212,88 +212,68 @@ static int squashfs_xattr_get(struct inode *inode, int name_index,
 }
 
 
-/*
- * User namespace support
- */
-static size_t squashfs_user_list(struct dentry *d, char *list, size_t list_size,
-       const char *name, size_t name_len, int type)
+static size_t squashfs_xattr_handler_list(const struct xattr_handler *handler,
+                                         struct dentry *d, char *list,
+                                         size_t list_size, const char *name,
+                                         size_t name_len)
 {
-       if (list && XATTR_USER_PREFIX_LEN <= list_size)
-               memcpy(list, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
-       return XATTR_USER_PREFIX_LEN;
+       int len = strlen(handler->prefix);
+
+       if (list && len <= list_size)
+               memcpy(list, handler->prefix, len);
+       return len;
 }
 
-static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
-       size_t size, int type)
+static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
+                                     struct dentry *d, const char *name,
+                                     void *buffer, size_t size)
 {
        if (name[0] == '\0')
                return  -EINVAL;
 
-       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_USER, name,
+       return squashfs_xattr_get(d_inode(d), handler->flags, name,
                buffer, size);
 }
 
+/*
+ * User namespace support
+ */
 static const struct xattr_handler squashfs_xattr_user_handler = {
        .prefix = XATTR_USER_PREFIX,
-       .list   = squashfs_user_list,
-       .get    = squashfs_user_get
+       .flags  = SQUASHFS_XATTR_USER,
+       .list   = squashfs_xattr_handler_list,
+       .get    = squashfs_xattr_handler_get
 };
 
 /*
  * Trusted namespace support
  */
-static size_t squashfs_trusted_list(struct dentry *d, char *list,
-       size_t list_size, const char *name, size_t name_len, int type)
+static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler *handler,
+                                                 struct dentry *d, char *list,
+                                                 size_t list_size, const char *name,
+                                                 size_t name_len)
 {
        if (!capable(CAP_SYS_ADMIN))
                return 0;
-
-       if (list && XATTR_TRUSTED_PREFIX_LEN <= list_size)
-               memcpy(list, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
-       return XATTR_TRUSTED_PREFIX_LEN;
-}
-
-static int squashfs_trusted_get(struct dentry *d, const char *name,
-       void *buffer, size_t size, int type)
-{
-       if (name[0] == '\0')
-               return  -EINVAL;
-
-       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_TRUSTED, name,
-               buffer, size);
+       return squashfs_xattr_handler_list(handler, d, list, list_size, name,
+                                          name_len);
 }
 
 static const struct xattr_handler squashfs_xattr_trusted_handler = {
        .prefix = XATTR_TRUSTED_PREFIX,
-       .list   = squashfs_trusted_list,
-       .get    = squashfs_trusted_get
+       .flags  = SQUASHFS_XATTR_TRUSTED,
+       .list   = squashfs_trusted_xattr_handler_list,
+       .get    = squashfs_xattr_handler_get
 };
 
 /*
  * Security namespace support
  */
-static size_t squashfs_security_list(struct dentry *d, char *list,
-       size_t list_size, const char *name, size_t name_len, int type)
-{
-       if (list && XATTR_SECURITY_PREFIX_LEN <= list_size)
-               memcpy(list, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
-       return XATTR_SECURITY_PREFIX_LEN;
-}
-
-static int squashfs_security_get(struct dentry *d, const char *name,
-       void *buffer, size_t size, int type)
-{
-       if (name[0] == '\0')
-               return  -EINVAL;
-
-       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_SECURITY, name,
-               buffer, size);
-}
-
 static const struct xattr_handler squashfs_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
-       .list   = squashfs_security_list,
-       .get    = squashfs_security_get
+       .flags  = SQUASHFS_XATTR_SECURITY,
+       .list   = squashfs_xattr_handler_list,
+       .get    = squashfs_xattr_handler_get
 };
 
 static const struct xattr_handler *squashfs_xattr_handler(int type)
index e1236594fffec8d50b79eada956fdaadba663aff..dc1358b5ec95814c4e0f0ca0bec3d2b847029b24 100644 (file)
@@ -73,13 +73,26 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
        }
 
        if (grp->bin_attrs) {
-               for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
+               for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
+                       umode_t mode = (*bin_attr)->attr.mode;
+
                        if (update)
                                kernfs_remove_by_name(parent,
                                                (*bin_attr)->attr.name);
+                       if (grp->is_bin_visible) {
+                               mode = grp->is_bin_visible(kobj, *bin_attr, i);
+                               if (!mode)
+                                       continue;
+                       }
+
+                       WARN(mode & ~(SYSFS_PREALLOC | 0664),
+                            "Attribute %s: Invalid permissions 0%o\n",
+                            (*bin_attr)->attr.name, mode);
+
+                       mode &= SYSFS_PREALLOC | 0664;
                        error = sysfs_add_file_mode_ns(parent,
                                        &(*bin_attr)->attr, true,
-                                       (*bin_attr)->attr.mode, NULL);
+                                       mode, NULL);
                        if (error)
                                break;
                }
index 590ad9206e3f4e761d2c2ad95cfaedfa76b47e16..02fa1dcc5969f6b596a6c527170fcf9193c437e5 100644 (file)
@@ -162,15 +162,8 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
                inode->i_fop = &sysv_dir_operations;
                inode->i_mapping->a_ops = &sysv_aops;
        } else if (S_ISLNK(inode->i_mode)) {
-               if (inode->i_blocks) {
-                       inode->i_op = &sysv_symlink_inode_operations;
-                       inode->i_mapping->a_ops = &sysv_aops;
-               } else {
-                       inode->i_op = &simple_symlink_inode_operations;
-                       inode->i_link = (char *)SYSV_I(inode)->i_data;
-                       nd_terminate_link(inode->i_link, inode->i_size,
-                               sizeof(SYSV_I(inode)->i_data) - 1);
-               }
+               inode->i_op = &sysv_symlink_inode_operations;
+               inode->i_mapping->a_ops = &sysv_aops;
        } else
                init_special_inode(inode, inode->i_mode, rdev);
 }
index 8ee3133dd8e49af9f413025683236cf464a62f12..1fd90c0795374b6abae3d9787e1b898bd1819546 100644 (file)
@@ -2040,7 +2040,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        if (c->max_inode_sz > MAX_LFS_FILESIZE)
                sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
        sb->s_op = &ubifs_super_operations;
-       sb->s_xattr = ubifs_xattr_handlers;
 
        mutex_lock(&c->umount_mutex);
        err = mount_ubifs(c);
index 01142e129d168ccba3139992ce50df56c9acea3a..a5697de763f516f659b7f69e42e5eba4ad94efec 100644 (file)
@@ -1470,7 +1470,6 @@ extern spinlock_t ubifs_infos_lock;
 extern atomic_long_t ubifs_clean_zn_cnt;
 extern struct kmem_cache *ubifs_inode_slab;
 extern const struct super_operations ubifs_super_operations;
-extern const struct xattr_handler *ubifs_xattr_handlers[];
 extern const struct address_space_operations ubifs_file_address_operations;
 extern const struct file_operations ubifs_file_operations;
 extern const struct inode_operations ubifs_file_inode_operations;
index 259fbabf143d8cb8cf4e88df59268710fd420137..e8b01b721e99d3954e344686fc615c9455e4246c 100644 (file)
@@ -588,46 +588,6 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
        return err;
 }
 
-static size_t security_listxattr(struct dentry *d, char *list, size_t list_size,
-                                const char *name, size_t name_len, int flags)
-{
-       const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
-       const size_t total_len = prefix_len + name_len + 1;
-
-       if (list && total_len <= list_size) {
-               memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
-               memcpy(list + prefix_len, name, name_len);
-               list[prefix_len + name_len] = '\0';
-       }
-
-       return total_len;
-}
-
-static int security_getxattr(struct dentry *d, const char *name, void *buffer,
-                     size_t size, int flags)
-{
-       return ubifs_getxattr(d, name, buffer, size);
-}
-
-static int security_setxattr(struct dentry *d, const char *name,
-                            const void *value, size_t size, int flags,
-                            int handler_flags)
-{
-       return ubifs_setxattr(d, name, value, size, flags);
-}
-
-static const struct xattr_handler ubifs_xattr_security_handler = {
-       .prefix = XATTR_SECURITY_PREFIX,
-       .list   = security_listxattr,
-       .get    = security_getxattr,
-       .set    = security_setxattr,
-};
-
-const struct xattr_handler *ubifs_xattr_handlers[] = {
-       &ubifs_xattr_security_handler,
-       NULL,
-};
-
 static int init_xattrs(struct inode *inode, const struct xattr *xattr_array,
                      void *fs_info)
 {
index 072fee1258dd87e58d44ab3263909bab4f3a2e89..9b932b95d74e4faeb5653d1a3c4b11553d1e51e1 100644 (file)
@@ -720,7 +720,7 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->get(dentry, name, buffer, size, handler->flags);
+       return handler->get(handler, dentry, name, buffer, size);
 }
 
 /*
@@ -735,15 +735,15 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 
        if (!buffer) {
                for_each_xattr_handler(handlers, handler) {
-                       size += handler->list(dentry, NULL, 0, NULL, 0,
-                                             handler->flags);
+                       size += handler->list(handler, dentry, NULL, 0,
+                                             NULL, 0);
                }
        } else {
                char *buf = buffer;
 
                for_each_xattr_handler(handlers, handler) {
-                       size = handler->list(dentry, buf, buffer_size,
-                                            NULL, 0, handler->flags);
+                       size = handler->list(handler, dentry, buf, buffer_size,
+                                            NULL, 0);
                        if (size > buffer_size)
                                return -ERANGE;
                        buf += size;
@@ -767,7 +767,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(dentry, name, value, size, flags, handler->flags);
+       return handler->set(handler, dentry, name, value, size, flags);
 }
 
 /*
@@ -782,8 +782,7 @@ generic_removexattr(struct dentry *dentry, const char *name)
        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(dentry, name, NULL, 0,
-                           XATTR_REPLACE, handler->flags);
+       return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
@@ -791,6 +790,30 @@ EXPORT_SYMBOL(generic_listxattr);
 EXPORT_SYMBOL(generic_setxattr);
 EXPORT_SYMBOL(generic_removexattr);
 
+/**
+ * xattr_full_name  -  Compute full attribute name from suffix
+ *
+ * @handler:   handler of the xattr_handler operation
+ * @name:      name passed to the xattr_handler operation
+ *
+ * The get and set xattr handler operations are called with the remainder of
+ * the attribute name after skipping the handler's prefix: for example, "foo"
+ * is passed to the get operation of a handler with prefix "user." to get
+ * attribute "user.foo".  The full name is still "there" in the name though.
+ *
+ * Note: the list xattr handler operation when called from the vfs is passed a
+ * NULL name; some file systems use this operation internally, with varying
+ * semantics.
+ */
+const char *xattr_full_name(const struct xattr_handler *handler,
+                           const char *name)
+{
+       size_t prefix_len = strlen(handler->prefix);
+
+       return name - prefix_len;
+}
+EXPORT_SYMBOL(xattr_full_name);
+
 /*
  * Allocate new xattr and copy in the value; but leave the name to callers.
  */
index 8294f86441bfcdc108eb28ec57b7a449f31dd675..839b35ca21c69320c736ac636ef681b1362402ce 100644 (file)
 
 
 static int
-xfs_xattr_get(struct dentry *dentry, const char *name,
-               void *value, size_t size, int xflags)
+xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry,
+               const char *name, void *value, size_t size)
 {
+       int xflags = handler->flags;
        struct xfs_inode *ip = XFS_I(d_inode(dentry));
        int error, asize = size;
 
@@ -76,9 +77,10 @@ xfs_forget_acl(
 }
 
 static int
-xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
-               size_t size, int flags, int xflags)
+xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry,
+               const char *name, const void *value, size_t size, int flags)
 {
+       int                     xflags = handler->flags;
        struct xfs_inode        *ip = XFS_I(d_inode(dentry));
        int                     error;
 
index d11eff8a4efe95f92d8e75a18498017709ca096f..ad0a5ff3d4cd724128b36074d428f475155df1b4 100644 (file)
@@ -390,39 +390,6 @@ struct acpi_data_node {
        struct completion kobj_done;
 };
 
-static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent)
-{
-       bool ret = false;
-
-       if (!adev)
-               return ret;
-
-       /**
-        * Currently, we only support _CCA=1 (i.e. coherent_dma=1)
-        * This should be equivalent to specifyig dma-coherent for
-        * a device in OF.
-        *
-        * For the case when _CCA=0 (i.e. coherent_dma=0 && cca_seen=1),
-        * There are two cases:
-        * case 1. Do not support and disable DMA.
-        * case 2. Support but rely on arch-specific cache maintenance for
-        *         non-coherence DMA operations.
-        * Currently, we implement case 1 above.
-        *
-        * For the case when _CCA is missing (i.e. cca_seen=0) and
-        * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
-        * and fallback to arch-specific default handling.
-        *
-        * See acpi_init_coherency() for more info.
-        */
-       if (adev->flags.coherent_dma) {
-               ret = true;
-               if (coherent)
-                       *coherent = adev->flags.coherent_dma;
-       }
-       return ret;
-}
-
 static inline bool is_acpi_node(struct fwnode_handle *fwnode)
 {
        return fwnode && (fwnode->type == FWNODE_ACPI
@@ -595,6 +562,9 @@ struct acpi_pci_root {
 
 /* helper */
 
+bool acpi_dma_supported(struct acpi_device *adev);
+enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
                                           u64 address, bool check_children);
 int acpi_is_root_bridge(acpi_handle);
index 72d8803832ff64ef5e53b666abdcb7ea21d44a61..1bfa602958f2a2f7beb16fab8f98263d198c652b 100644 (file)
@@ -163,9 +163,10 @@ static inline __must_check long __copy_to_user(void __user *to,
 
 #define put_user(x, ptr)                                       \
 ({                                                             \
+       void *__p = (ptr);                                      \
        might_fault();                                          \
-       access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)) ?            \
-               __put_user(x, ptr) :                            \
+       access_ok(VERIFY_WRITE, __p, sizeof(*ptr)) ?            \
+               __put_user((x), ((__typeof__(*(ptr)) *)__p)) :  \
                -EFAULT;                                        \
 })
 
@@ -225,9 +226,10 @@ extern int __put_user_bad(void) __attribute__((noreturn));
 
 #define get_user(x, ptr)                                       \
 ({                                                             \
+       const void *__p = (ptr);                                \
        might_fault();                                          \
-       access_ok(VERIFY_READ, ptr, sizeof(*ptr)) ?             \
-               __get_user(x, ptr) :                            \
+       access_ok(VERIFY_READ, __p, sizeof(*ptr)) ?             \
+               __get_user((x), (__typeof__(*(ptr)) *)__p) :    \
                -EFAULT;                                        \
 })
 
index e67aeac2aee05c077eec5a47abc9d73eef6831d6..4b74c97d297a3e8f24a50de057cb4db79750f39c 100644 (file)
@@ -136,6 +136,9 @@ drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
 
 void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
 
+void
+drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
+
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
 int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
index 9c747cb14ad88809b9c77df72d8c0563f0230319..d2f41477f8ae77600a8683890b3615766b9a3701 100644 (file)
@@ -342,10 +342,10 @@ int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid,
                               struct irq_phys_map *map, bool level);
 void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
-int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu);
 struct irq_phys_map *kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu,
                                           int virt_irq, int irq);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map);
 
 #define irqchip_in_kernel(k)   (!!((k)->arch.vgic.in_kernel))
 #define vgic_initialized(k)    (!!((k)->arch.vgic.nr_cpus))
index ebfac2fe0c813bea9d98d01e8dc4f244e1bd97d4..05483393999534d91425b01c4573a5a4aa494fbc 100644 (file)
@@ -601,11 +601,16 @@ static inline int acpi_device_modalias(struct device *dev,
        return -ENODEV;
 }
 
-static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent)
+static inline bool acpi_dma_supported(struct acpi_device *adev)
 {
        return false;
 }
 
+static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
+{
+       return DEV_DMA_NOT_SUPPORTED;
+}
+
 #define ACPI_PTR(_ptr) (NULL)
 
 #endif /* !CONFIG_ACPI */
index 641e5a3ed58c4d2e1d8fb5c64c216eb3b5b821a5..0fb65843ec1e8522461dfe2d308c06e6fe33e2af 100644 (file)
@@ -265,7 +265,7 @@ static inline unsigned int blk_qc_t_to_queue_num(blk_qc_t cookie)
 
 static inline unsigned int blk_qc_t_to_tag(blk_qc_t cookie)
 {
-       return cookie & 0xffff;
+       return cookie & ((1u << BLK_QC_T_SHIFT) - 1);
 }
 
 #endif /* __LINUX_BLK_TYPES_H */
index 3fe27f8d91f04f83751453f19f4e4bb6a4f9a2b4..c0d2b7927c1f5a73afc2a56552116d86c04ca947 100644 (file)
@@ -794,6 +794,8 @@ extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
 extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
                         struct scsi_ioctl_command __user *);
 
+extern int blk_queue_enter(struct request_queue *q, gfp_t gfp);
+extern void blk_queue_exit(struct request_queue *q);
 extern void blk_start_queue(struct request_queue *q);
 extern void blk_stop_queue(struct request_queue *q);
 extern void blk_sync_queue(struct request_queue *q);
index 397c5cd09794854ebc8891fac59b4dfa50e7e141..3e3799cdc6e66d719fed8ae9adc8539d4e2cb0c6 100644 (file)
@@ -29,8 +29,9 @@
 #define CEPH_OPT_NOSHARE          (1<<1) /* don't share client with other sbs */
 #define CEPH_OPT_MYIP             (1<<2) /* specified my ip */
 #define CEPH_OPT_NOCRC            (1<<3) /* no data crc on writes */
-#define CEPH_OPT_NOMSGAUTH       (1<<4) /* not require cephx message signature */
+#define CEPH_OPT_NOMSGAUTH       (1<<4) /* don't require msg signing feat */
 #define CEPH_OPT_TCP_NODELAY     (1<<5) /* TCP_NODELAY on TCP sockets */
+#define CEPH_OPT_NOMSGSIGN       (1<<6) /* don't sign msgs */
 
 #define CEPH_OPT_DEFAULT   (CEPH_OPT_TCP_NODELAY)
 
@@ -137,6 +138,7 @@ struct ceph_client {
 #endif
 };
 
+#define from_msgr(ms)  container_of(ms, struct ceph_client, msgr)
 
 
 /*
index b2371d9b51fac6ea69032576ac1c3cddfc104016..71b1d6cdcb5d1fc53dd45fa3950e138cfac19dfe 100644 (file)
@@ -43,10 +43,9 @@ struct ceph_connection_operations {
        struct ceph_msg * (*alloc_msg) (struct ceph_connection *con,
                                        struct ceph_msg_header *hdr,
                                        int *skip);
-       int (*sign_message) (struct ceph_connection *con, struct ceph_msg *msg);
 
-       int (*check_message_signature) (struct ceph_connection *con,
-                                       struct ceph_msg *msg);
+       int (*sign_message) (struct ceph_msg *msg);
+       int (*check_message_signature) (struct ceph_msg *msg);
 };
 
 /* use format string %s%d */
@@ -58,8 +57,6 @@ struct ceph_messenger {
 
        atomic_t stopping;
        possible_net_t net;
-       bool nocrc;
-       bool tcp_nodelay;
 
        /*
         * the global_seq counts connections i (attempt to) initiate
@@ -67,9 +64,6 @@ struct ceph_messenger {
         */
        u32 global_seq;
        spinlock_t global_seq_lock;
-
-       u64 supported_features;
-       u64 required_features;
 };
 
 enum ceph_msg_data_type {
@@ -268,11 +262,7 @@ extern void ceph_msgr_exit(void);
 extern void ceph_msgr_flush(void);
 
 extern void ceph_messenger_init(struct ceph_messenger *msgr,
-                       struct ceph_entity_addr *myaddr,
-                       u64 supported_features,
-                       u64 required_features,
-                       bool nocrc,
-                       bool tcp_nodelay);
+                               struct ceph_entity_addr *myaddr);
 extern void ceph_messenger_fini(struct ceph_messenger *msgr);
 
 extern void ceph_con_init(struct ceph_connection *con, void *private,
index 63a36e89d0eb6b3f718d7058b723291662c186d3..758a029011b11a3d1d2c1acfe9fa171e82a55343 100644 (file)
@@ -125,86 +125,33 @@ struct configfs_attribute {
        const char              *ca_name;
        struct module           *ca_owner;
        umode_t                 ca_mode;
+       ssize_t (*show)(struct config_item *, char *);
+       ssize_t (*store)(struct config_item *, const char *, size_t);
 };
 
-/*
- * Users often need to create attribute structures for their configurable
- * attributes, containing a configfs_attribute member and function pointers
- * for the show() and store() operations on that attribute. If they don't
- * need anything else on the extended attribute structure, they can use
- * this macro to define it  The argument _item is the name of the
- * config_item structure.
- */
-#define CONFIGFS_ATTR_STRUCT(_item)                                    \
-struct _item##_attribute {                                             \
-       struct configfs_attribute attr;                                 \
-       ssize_t (*show)(struct _item *, char *);                        \
-       ssize_t (*store)(struct _item *, const char *, size_t);         \
+#define CONFIGFS_ATTR(_pfx, _name)                     \
+static struct configfs_attribute _pfx##attr_##_name = {        \
+       .ca_name        = __stringify(_name),           \
+       .ca_mode        = S_IRUGO | S_IWUSR,            \
+       .ca_owner       = THIS_MODULE,                  \
+       .show           = _pfx##_name##_show,           \
+       .store          = _pfx##_name##_store,          \
 }
 
-/*
- * With the extended attribute structure, users can use this macro
- * (similar to sysfs' __ATTR) to make defining attributes easier.
- * An example:
- * #define MYITEM_ATTR(_name, _mode, _show, _store)    \
- * struct myitem_attribute childless_attr_##_name =    \
- *         __CONFIGFS_ATTR(_name, _mode, _show, _store)
- */
-#define __CONFIGFS_ATTR(_name, _mode, _show, _store)                   \
-{                                                                      \
-       .attr   = {                                                     \
-                       .ca_name = __stringify(_name),                  \
-                       .ca_mode = _mode,                               \
-                       .ca_owner = THIS_MODULE,                        \
-       },                                                              \
-       .show   = _show,                                                \
-       .store  = _store,                                               \
-}
-/* Here is a readonly version, only requiring a show() operation */
-#define __CONFIGFS_ATTR_RO(_name, _show)                               \
-{                                                                      \
-       .attr   = {                                                     \
-                       .ca_name = __stringify(_name),                  \
-                       .ca_mode = 0444,                                \
-                       .ca_owner = THIS_MODULE,                        \
-       },                                                              \
-       .show   = _show,                                                \
+#define CONFIGFS_ATTR_RO(_pfx, _name)                  \
+static struct configfs_attribute _pfx##attr_##_name = {        \
+       .ca_name        = __stringify(_name),           \
+       .ca_mode        = S_IRUGO,                      \
+       .ca_owner       = THIS_MODULE,                  \
+       .show           = _pfx##_name##_show,           \
 }
 
-/*
- * With these extended attributes, the simple show_attribute() and
- * store_attribute() operations need to call the show() and store() of the
- * attributes.  This is a common pattern, so we provide a macro to define
- * them.  The argument _item is the name of the config_item structure.
- * This macro expects the attributes to be named "struct <name>_attribute"
- * and the function to_<name>() to exist;
- */
-#define CONFIGFS_ATTR_OPS(_item)                                       \
-static ssize_t _item##_attr_show(struct config_item *item,             \
-                                struct configfs_attribute *attr,       \
-                                char *page)                            \
-{                                                                      \
-       struct _item *_item = to_##_item(item);                         \
-       struct _item##_attribute *_item##_attr =                        \
-               container_of(attr, struct _item##_attribute, attr);     \
-       ssize_t ret = 0;                                                \
-                                                                       \
-       if (_item##_attr->show)                                         \
-               ret = _item##_attr->show(_item, page);                  \
-       return ret;                                                     \
-}                                                                      \
-static ssize_t _item##_attr_store(struct config_item *item,            \
-                                 struct configfs_attribute *attr,      \
-                                 const char *page, size_t count)       \
-{                                                                      \
-       struct _item *_item = to_##_item(item);                         \
-       struct _item##_attribute *_item##_attr =                        \
-               container_of(attr, struct _item##_attribute, attr);     \
-       ssize_t ret = -EINVAL;                                          \
-                                                                       \
-       if (_item##_attr->store)                                        \
-               ret = _item##_attr->store(_item, page, count);          \
-       return ret;                                                     \
+#define CONFIGFS_ATTR_WO(_pfx, _name)                  \
+static struct configfs_attribute _pfx##attr_##_name = {        \
+       .ca_name        = __stringify(_name),           \
+       .ca_mode        = S_IWUSR,                      \
+       .ca_owner       = THIS_MODULE,                  \
+       .store          = _pfx##_name##_store,          \
 }
 
 /*
@@ -223,8 +170,6 @@ static ssize_t _item##_attr_store(struct config_item *item,         \
  */
 struct configfs_item_operations {
        void (*release)(struct config_item *);
-       ssize_t (*show_attribute)(struct config_item *, struct configfs_attribute *,char *);
-       ssize_t (*store_attribute)(struct config_item *,struct configfs_attribute *,const char *, size_t);
        int (*allow_link)(struct config_item *src, struct config_item *target);
        int (*drop_link)(struct config_item *src, struct config_item *target);
 };
@@ -252,6 +197,16 @@ static inline struct configfs_subsystem *to_configfs_subsystem(struct config_gro
 int configfs_register_subsystem(struct configfs_subsystem *subsys);
 void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 
+int configfs_register_group(struct config_group *parent_group,
+                           struct config_group *group);
+void configfs_unregister_group(struct config_group *group);
+
+struct config_group *
+configfs_register_default_group(struct config_group *parent_group,
+                               const char *name,
+                               struct config_item_type *item_type);
+void configfs_unregister_default_group(struct config_group *group);
+
 /* These functions can sleep and can alloc with GFP_KERNEL */
 /* WARNING: These cannot be called underneath configfs callbacks!! */
 int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
index 008fc67d0d963ea811feb5cdfcdf1c750f407864..68b575afe5f5909f78b88f88c4dcbd086ef19720 100644 (file)
 #ifdef CONFIG_CONTEXT_TRACKING
 extern void context_tracking_cpu_set(int cpu);
 
+/* Called with interrupts disabled.  */
+extern void __context_tracking_enter(enum ctx_state state);
+extern void __context_tracking_exit(enum ctx_state state);
+
 extern void context_tracking_enter(enum ctx_state state);
 extern void context_tracking_exit(enum ctx_state state);
 extern void context_tracking_user_enter(void);
@@ -18,13 +22,13 @@ extern void context_tracking_user_exit(void);
 static inline void user_enter(void)
 {
        if (context_tracking_is_enabled())
-               context_tracking_user_enter();
+               context_tracking_enter(CONTEXT_USER);
 
 }
 static inline void user_exit(void)
 {
        if (context_tracking_is_enabled())
-               context_tracking_user_exit();
+               context_tracking_exit(CONTEXT_USER);
 }
 
 static inline enum ctx_state exception_enter(void)
@@ -88,13 +92,13 @@ static inline void guest_enter(void)
                current->flags |= PF_VCPU;
 
        if (context_tracking_is_enabled())
-               context_tracking_enter(CONTEXT_GUEST);
+               __context_tracking_enter(CONTEXT_GUEST);
 }
 
 static inline void guest_exit(void)
 {
        if (context_tracking_is_enabled())
-               context_tracking_exit(CONTEXT_GUEST);
+               __context_tracking_exit(CONTEXT_GUEST);
 
        if (vtime_accounting_enabled())
                vtime_guest_exit(current);
index 6523109e136dfa6c2ca16ceab13cc637a13339a5..8942af0813e38cc267d4efbcef6e737f32fc7def 100644 (file)
@@ -271,7 +271,7 @@ static inline int gfpflags_to_migratetype(const gfp_t gfp_flags)
 
 static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
 {
-       return gfp_flags & __GFP_DIRECT_RECLAIM;
+       return (bool __force)(gfp_flags & __GFP_DIRECT_RECLAIM);
 }
 
 #ifdef CONFIG_HIGHMEM
index 4e6861605050489e4ca3df78d94520993805c0ce..ce824db48d64c7fd29fc41babb0df6923da0774f 100644 (file)
@@ -9,6 +9,7 @@
 #define __LINUX_IRQCHIP_MIPS_GIC_H
 
 #include <linux/clocksource.h>
+#include <linux/ioport.h>
 
 #define GIC_MAX_INTRS                  256
 
 #define GIC_SHARED_TO_HWIRQ(x) (GIC_SHARED_HWIRQ_BASE + (x))
 #define GIC_HWIRQ_TO_SHARED(x) ((x) - GIC_SHARED_HWIRQ_BASE)
 
+#ifdef CONFIG_MIPS_GIC
+
 extern unsigned int gic_present;
 
 extern void gic_init(unsigned long gic_base_addr,
@@ -264,4 +267,18 @@ extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 extern int gic_get_c0_fdc_int(void);
+extern int gic_get_usm_range(struct resource *gic_usm_res);
+
+#else /* CONFIG_MIPS_GIC */
+
+#define gic_present    0
+
+static inline int gic_get_usm_range(struct resource *gic_usm_res)
+{
+       /* Shouldn't be called. */
+       return -1;
+}
+
+#endif /* CONFIG_MIPS_GIC */
+
 #endif /* __LINUX_IRQCHIP_MIPS_GIC_H */
index 242a6d2b53ff2713b21496072289bbb576754fb6..c923350ca20a5a53453576f360e52498de232abe 100644 (file)
@@ -460,6 +460,17 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
             (vcpup = kvm_get_vcpu(kvm, idx)) != NULL; \
             idx++)
 
+static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
+{
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       kvm_for_each_vcpu(i, vcpu, kvm)
+               if (vcpu->vcpu_id == id)
+                       return vcpu;
+       return NULL;
+}
+
 #define kvm_for_each_memslot(memslot, slots)   \
        for (memslot = &slots->memslots[0];     \
              memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\
@@ -1183,4 +1194,5 @@ void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *);
 int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq,
                                  uint32_t guest_irq, bool set);
 #endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */
+
 #endif
index 69c9057e1ab89330b1ed22cd0681bf5440ce0096..3db5552b17d5b5e489eb3d5bb3c6a12fcb779b29 100644 (file)
@@ -58,7 +58,6 @@ enum {
 struct nvm_id_group {
        u8      mtype;
        u8      fmtype;
-       u16     res16;
        u8      num_ch;
        u8      num_lun;
        u8      num_pln;
@@ -74,9 +73,9 @@ struct nvm_id_group {
        u32     tbet;
        u32     tbem;
        u32     mpos;
+       u32     mccap;
        u16     cpar;
-       u8      res[913];
-} __packed;
+};
 
 struct nvm_addr_format {
        u8      ch_offset;
@@ -91,19 +90,15 @@ struct nvm_addr_format {
        u8      pg_len;
        u8      sect_offset;
        u8      sect_len;
-       u8      res[4];
 };
 
 struct nvm_id {
        u8      ver_id;
        u8      vmnt;
        u8      cgrps;
-       u8      res[5];
        u32     cap;
        u32     dom;
        struct nvm_addr_format ppaf;
-       u8      ppat;
-       u8      resv[224];
        struct nvm_id_group groups[4];
 } __packed;
 
@@ -123,39 +118,28 @@ struct nvm_tgt_instance {
 #define NVM_VERSION_MINOR 0
 #define NVM_VERSION_PATCH 0
 
-#define NVM_SEC_BITS (8)
-#define NVM_PL_BITS  (6)
-#define NVM_PG_BITS  (16)
 #define NVM_BLK_BITS (16)
-#define NVM_LUN_BITS (10)
+#define NVM_PG_BITS  (16)
+#define NVM_SEC_BITS (8)
+#define NVM_PL_BITS  (8)
+#define NVM_LUN_BITS (8)
 #define NVM_CH_BITS  (8)
 
 struct ppa_addr {
+       /* Generic structure for all addresses */
        union {
-               /* Channel-based PPA format in nand 4x2x2x2x8x10 */
-               struct {
-                       u64 ch          : 4;
-                       u64 sec         : 2; /* 4 sectors per page */
-                       u64 pl          : 2; /* 4 planes per LUN */
-                       u64 lun         : 2; /* 4 LUNs per channel */
-                       u64 pg          : 8; /* 256 pages per block */
-                       u64 blk         : 10;/* 1024 blocks per plane */
-                       u64 resved              : 36;
-               } chnl;
-
-               /* Generic structure for all addresses */
                struct {
+                       u64 blk         : NVM_BLK_BITS;
+                       u64 pg          : NVM_PG_BITS;
                        u64 sec         : NVM_SEC_BITS;
                        u64 pl          : NVM_PL_BITS;
-                       u64 pg          : NVM_PG_BITS;
-                       u64 blk         : NVM_BLK_BITS;
                        u64 lun         : NVM_LUN_BITS;
                        u64 ch          : NVM_CH_BITS;
                } g;
 
                u64 ppa;
        };
-} __packed;
+};
 
 struct nvm_rq {
        struct nvm_tgt_instance *ins;
@@ -191,11 +175,11 @@ static inline void *nvm_rq_to_pdu(struct nvm_rq *rqdata)
 struct nvm_block;
 
 typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
-typedef int (nvm_bb_update_fn)(u32, void *, unsigned int, void *);
+typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
 typedef int (nvm_id_fn)(struct request_queue *, struct nvm_id *);
 typedef int (nvm_get_l2p_tbl_fn)(struct request_queue *, u64, u32,
                                nvm_l2p_update_fn *, void *);
-typedef int (nvm_op_bb_tbl_fn)(struct request_queue *, int, unsigned int,
+typedef int (nvm_op_bb_tbl_fn)(struct request_queue *, struct ppa_addr, int,
                                nvm_bb_update_fn *, void *);
 typedef int (nvm_op_set_bb_fn)(struct request_queue *, struct nvm_rq *, int);
 typedef int (nvm_submit_io_fn)(struct request_queue *, struct nvm_rq *);
@@ -210,7 +194,7 @@ struct nvm_dev_ops {
        nvm_id_fn               *identity;
        nvm_get_l2p_tbl_fn      *get_l2p_tbl;
        nvm_op_bb_tbl_fn        *get_bb_tbl;
-       nvm_op_set_bb_fn        *set_bb;
+       nvm_op_set_bb_fn        *set_bb_tbl;
 
        nvm_submit_io_fn        *submit_io;
        nvm_erase_blk_fn        *erase_block;
@@ -220,7 +204,7 @@ struct nvm_dev_ops {
        nvm_dev_dma_alloc_fn    *dev_dma_alloc;
        nvm_dev_dma_free_fn     *dev_dma_free;
 
-       uint8_t                 max_phys_sect;
+       unsigned int            max_phys_sect;
 };
 
 struct nvm_lun {
@@ -229,7 +213,9 @@ struct nvm_lun {
        int lun_id;
        int chnl_id;
 
+       unsigned int nr_inuse_blocks;   /* Number of used blocks */
        unsigned int nr_free_blocks;    /* Number of unused blocks */
+       unsigned int nr_bad_blocks;     /* Number of bad blocks */
        struct nvm_block *blocks;
 
        spinlock_t lock;
@@ -263,8 +249,7 @@ struct nvm_dev {
        int blks_per_lun;
        int sec_size;
        int oob_size;
-       int addr_mode;
-       struct nvm_addr_format addr_format;
+       struct nvm_addr_format ppaf;
 
        /* Calculated/Cached values. These do not reflect the actual usable
         * blocks at run-time.
@@ -290,118 +275,45 @@ struct nvm_dev {
        char name[DISK_NAME_LEN];
 };
 
-/* fallback conversion */
-static struct ppa_addr __generic_to_linear_addr(struct nvm_dev *dev,
-                                                       struct ppa_addr r)
-{
-       struct ppa_addr l;
-
-       l.ppa = r.g.sec +
-               r.g.pg  * dev->sec_per_pg +
-               r.g.blk * (dev->pgs_per_blk *
-                               dev->sec_per_pg) +
-               r.g.lun * (dev->blks_per_lun *
-                               dev->pgs_per_blk *
-                               dev->sec_per_pg) +
-               r.g.ch * (dev->blks_per_lun *
-                               dev->pgs_per_blk *
-                               dev->luns_per_chnl *
-                               dev->sec_per_pg);
-
-       return l;
-}
-
-/* fallback conversion */
-static struct ppa_addr __linear_to_generic_addr(struct nvm_dev *dev,
-                                                       struct ppa_addr r)
+static inline struct ppa_addr generic_to_dev_addr(struct nvm_dev *dev,
+                                               struct ppa_addr r)
 {
        struct ppa_addr l;
-       int secs, pgs, blks, luns;
-       sector_t ppa = r.ppa;
 
-       l.ppa = 0;
-
-       div_u64_rem(ppa, dev->sec_per_pg, &secs);
-       l.g.sec = secs;
-
-       sector_div(ppa, dev->sec_per_pg);
-       div_u64_rem(ppa, dev->sec_per_blk, &pgs);
-       l.g.pg = pgs;
-
-       sector_div(ppa, dev->pgs_per_blk);
-       div_u64_rem(ppa, dev->blks_per_lun, &blks);
-       l.g.blk = blks;
-
-       sector_div(ppa, dev->blks_per_lun);
-       div_u64_rem(ppa, dev->luns_per_chnl, &luns);
-       l.g.lun = luns;
-
-       sector_div(ppa, dev->luns_per_chnl);
-       l.g.ch = ppa;
+       l.ppa = ((u64)r.g.blk) << dev->ppaf.blk_offset;
+       l.ppa |= ((u64)r.g.pg) << dev->ppaf.pg_offset;
+       l.ppa |= ((u64)r.g.sec) << dev->ppaf.sect_offset;
+       l.ppa |= ((u64)r.g.pl) << dev->ppaf.pln_offset;
+       l.ppa |= ((u64)r.g.lun) << dev->ppaf.lun_offset;
+       l.ppa |= ((u64)r.g.ch) << dev->ppaf.ch_offset;
 
        return l;
 }
 
-static struct ppa_addr __generic_to_chnl_addr(struct ppa_addr r)
+static inline struct ppa_addr dev_to_generic_addr(struct nvm_dev *dev,
+                                               struct ppa_addr r)
 {
        struct ppa_addr l;
 
-       l.ppa = 0;
-
-       l.chnl.sec = r.g.sec;
-       l.chnl.pl = r.g.pl;
-       l.chnl.pg = r.g.pg;
-       l.chnl.blk = r.g.blk;
-       l.chnl.lun = r.g.lun;
-       l.chnl.ch = r.g.ch;
-
-       return l;
-}
-
-static struct ppa_addr __chnl_to_generic_addr(struct ppa_addr r)
-{
-       struct ppa_addr l;
-
-       l.ppa = 0;
-
-       l.g.sec = r.chnl.sec;
-       l.g.pl = r.chnl.pl;
-       l.g.pg = r.chnl.pg;
-       l.g.blk = r.chnl.blk;
-       l.g.lun = r.chnl.lun;
-       l.g.ch = r.chnl.ch;
+       /*
+        * (r.ppa << X offset) & X len bitmask. X eq. blk, pg, etc.
+        */
+       l.g.blk = (r.ppa >> dev->ppaf.blk_offset) &
+                                       (((1 << dev->ppaf.blk_len) - 1));
+       l.g.pg |= (r.ppa >> dev->ppaf.pg_offset) &
+                                       (((1 << dev->ppaf.pg_len) - 1));
+       l.g.sec |= (r.ppa >> dev->ppaf.sect_offset) &
+                                       (((1 << dev->ppaf.sect_len) - 1));
+       l.g.pl |= (r.ppa >> dev->ppaf.pln_offset) &
+                                       (((1 << dev->ppaf.pln_len) - 1));
+       l.g.lun |= (r.ppa >> dev->ppaf.lun_offset) &
+                                       (((1 << dev->ppaf.lun_len) - 1));
+       l.g.ch |= (r.ppa >> dev->ppaf.ch_offset) &
+                                       (((1 << dev->ppaf.ch_len) - 1));
 
        return l;
 }
 
-static inline struct ppa_addr addr_to_generic_mode(struct nvm_dev *dev,
-                                               struct ppa_addr gppa)
-{
-       switch (dev->addr_mode) {
-       case NVM_ADDRMODE_LINEAR:
-               return __linear_to_generic_addr(dev, gppa);
-       case NVM_ADDRMODE_CHANNEL:
-               return __chnl_to_generic_addr(gppa);
-       default:
-               BUG();
-       }
-       return gppa;
-}
-
-static inline struct ppa_addr generic_to_addr_mode(struct nvm_dev *dev,
-                                               struct ppa_addr gppa)
-{
-       switch (dev->addr_mode) {
-       case NVM_ADDRMODE_LINEAR:
-               return __generic_to_linear_addr(dev, gppa);
-       case NVM_ADDRMODE_CHANNEL:
-               return __generic_to_chnl_addr(gppa);
-       default:
-               BUG();
-       }
-       return gppa;
-}
-
 static inline int ppa_empty(struct ppa_addr ppa_addr)
 {
        return (ppa_addr.ppa == ADDR_EMPTY);
@@ -468,7 +380,7 @@ typedef int (nvmm_end_io_fn)(struct nvm_rq *, int);
 typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *,
                                                                unsigned long);
 typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int);
-typedef void (nvmm_free_blocks_print_fn)(struct nvm_dev *);
+typedef void (nvmm_lun_info_print_fn)(struct nvm_dev *);
 
 struct nvmm_type {
        const char *name;
@@ -492,7 +404,7 @@ struct nvmm_type {
        nvmm_get_lun_fn *get_lun;
 
        /* Statistics */
-       nvmm_free_blocks_print_fn *free_blocks_print;
+       nvmm_lun_info_print_fn *lun_info_print;
        struct list_head list;
 };
 
index e6982ac3200d65a537f2561bd51c2a0696b62e70..a57f0dfb6db7f2c0e0e268397b261fe8b45efa89 100644 (file)
@@ -16,6 +16,7 @@
 #define MARVELL_PHY_ID_88E1318S                0x01410e90
 #define MARVELL_PHY_ID_88E1116R                0x01410e40
 #define MARVELL_PHY_ID_88E1510         0x01410dd0
+#define MARVELL_PHY_ID_88E1540         0x01410eb0
 #define MARVELL_PHY_ID_88E3016         0x01410e60
 
 /* struct phy_device dev_flags definitions */
index c45c089bfdaca9a91f32832102ff32291444884f..6e8b5b270ffeada870b3cdcd638530f2479b84ee 100644 (file)
@@ -142,6 +142,13 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
 }
 #endif /* mul_u64_u32_shr */
 
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+       return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_shr */
+
 #else
 
 #ifndef mul_u64_u32_shr
@@ -161,6 +168,79 @@ static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
 }
 #endif /* mul_u64_u32_shr */
 
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
+{
+       union {
+               u64 ll;
+               struct {
+#ifdef __BIG_ENDIAN
+                       u32 high, low;
+#else
+                       u32 low, high;
+#endif
+               } l;
+       } rl, rm, rn, rh, a0, b0;
+       u64 c;
+
+       a0.ll = a;
+       b0.ll = b;
+
+       rl.ll = (u64)a0.l.low * b0.l.low;
+       rm.ll = (u64)a0.l.low * b0.l.high;
+       rn.ll = (u64)a0.l.high * b0.l.low;
+       rh.ll = (u64)a0.l.high * b0.l.high;
+
+       /*
+        * Each of these lines computes a 64-bit intermediate result into "c",
+        * starting at bits 32-95.  The low 32-bits go into the result of the
+        * multiplication, the high 32-bits are carried into the next step.
+        */
+       rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
+       rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
+       rh.l.high = (c >> 32) + rh.l.high;
+
+       /*
+        * The 128-bit result of the multiplication is in rl.ll and rh.ll,
+        * shift it right and throw away the high part of the result.
+        */
+       if (shift == 0)
+               return rl.ll;
+       if (shift < 64)
+               return (rl.ll >> shift) | (rh.ll << (64 - shift));
+       return rh.ll >> (shift & 63);
+}
+#endif /* mul_u64_u64_shr */
+
 #endif
 
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+       union {
+               u64 ll;
+               struct {
+#ifdef __BIG_ENDIAN
+                       u32 high, low;
+#else
+                       u32 low, high;
+#endif
+               } l;
+       } u, rl, rh;
+
+       u.ll = a;
+       rl.ll = (u64)u.l.low * mul;
+       rh.ll = (u64)u.l.high * mul + rl.l.high;
+
+       /* Bits 32-63 of the result will be in rh.l.low. */
+       rl.l.high = do_div(rh.ll, divisor);
+
+       /* Bits 0-31 of the result will be in rl.l.low. */
+       do_div(rl.ll, divisor);
+
+       rl.l.high = rh.l.low;
+       return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
 #endif /* _LINUX_MATH64_H */
index da72671a42fa6ed14d81a875c0fb8e6a2e66284f..494682ce4bf38b2c308dae7ad4e0bf1cab600495 100644 (file)
@@ -255,5 +255,6 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
 /* sysfs stuff */
 extern struct attribute_group cros_ec_attr_group;
 extern struct attribute_group cros_ec_lightbar_attr_group;
+extern struct attribute_group cros_ec_vbc_attr_group;
 
 #endif /* __LINUX_MFD_CROS_EC_H */
index dd2097455a2e3b54cbb69c409bbe8fa7463264ec..1565324eb620cc22931aa93e5a4e0f8b7a332460 100644 (file)
@@ -453,26 +453,28 @@ struct mlx5_ifc_per_protocol_networking_offload_caps_bits {
        u8         lro_cap[0x1];
        u8         lro_psh_flag[0x1];
        u8         lro_time_stamp[0x1];
-       u8         reserved_0[0x6];
+       u8         reserved_0[0x3];
+       u8         self_lb_en_modifiable[0x1];
+       u8         reserved_1[0x2];
        u8         max_lso_cap[0x5];
-       u8         reserved_1[0x4];
+       u8         reserved_2[0x4];
        u8         rss_ind_tbl_cap[0x4];
-       u8         reserved_2[0x3];
+       u8         reserved_3[0x3];
        u8         tunnel_lso_const_out_ip_id[0x1];
-       u8         reserved_3[0x2];
+       u8         reserved_4[0x2];
        u8         tunnel_statless_gre[0x1];
        u8         tunnel_stateless_vxlan[0x1];
 
-       u8         reserved_4[0x20];
+       u8         reserved_5[0x20];
 
-       u8         reserved_5[0x10];
+       u8         reserved_6[0x10];
        u8         lro_min_mss_size[0x10];
 
-       u8         reserved_6[0x120];
+       u8         reserved_7[0x120];
 
        u8         lro_timer_supported_periods[4][0x20];
 
-       u8         reserved_7[0x600];
+       u8         reserved_8[0x600];
 };
 
 struct mlx5_ifc_roce_cap_bits {
@@ -4051,9 +4053,11 @@ struct mlx5_ifc_modify_tis_in_bits {
 };
 
 struct mlx5_ifc_modify_tir_bitmask_bits {
-       u8         reserved[0x20];
+       u8         reserved_0[0x20];
 
-       u8         reserved1[0x1f];
+       u8         reserved_1[0x1b];
+       u8         self_lb_en[0x1];
+       u8         reserved_2[0x3];
        u8         lro[0x1];
 };
 
index d20891465247dfaa983225ce9336b14c91cb7fab..67bfac1abfc1ac8bd95bf3ddcf35aac07145166b 100644 (file)
@@ -2068,20 +2068,23 @@ struct pcpu_sw_netstats {
        struct u64_stats_sync   syncp;
 };
 
-#define netdev_alloc_pcpu_stats(type)                          \
-({                                                             \
-       typeof(type) __percpu *pcpu_stats = alloc_percpu(type); \
-       if (pcpu_stats) {                                       \
-               int __cpu;                                      \
-               for_each_possible_cpu(__cpu) {                  \
-                       typeof(type) *stat;                     \
-                       stat = per_cpu_ptr(pcpu_stats, __cpu);  \
-                       u64_stats_init(&stat->syncp);           \
-               }                                               \
-       }                                                       \
-       pcpu_stats;                                             \
+#define __netdev_alloc_pcpu_stats(type, gfp)                           \
+({                                                                     \
+       typeof(type) __percpu *pcpu_stats = alloc_percpu_gfp(type, gfp);\
+       if (pcpu_stats) {                                               \
+               int __cpu;                                              \
+               for_each_possible_cpu(__cpu) {                          \
+                       typeof(type) *stat;                             \
+                       stat = per_cpu_ptr(pcpu_stats, __cpu);          \
+                       u64_stats_init(&stat->syncp);                   \
+               }                                                       \
+       }                                                               \
+       pcpu_stats;                                                     \
 })
 
+#define netdev_alloc_pcpu_stats(type)                                  \
+       __netdev_alloc_pcpu_stats(type, GFP_KERNEL);
+
 #include <linux/notifier.h>
 
 /* netdevice notifier chain. Please remember to update the rtnetlink
@@ -3854,6 +3857,11 @@ static inline bool netif_is_bridge_master(const struct net_device *dev)
        return dev->priv_flags & IFF_EBRIDGE;
 }
 
+static inline bool netif_is_bridge_port(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_BRIDGE_PORT;
+}
+
 static inline bool netif_is_ovs_master(const struct net_device *dev)
 {
        return dev->priv_flags & IFF_OPENVSWITCH;
index 48bb01edcf3047bb70b70188430080c5970583a8..0e1f433cc4b78537c24e0e5f410894655d90aa0e 100644 (file)
@@ -421,7 +421,7 @@ extern void ip_set_free(void *members);
 extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
 extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
 extern size_t ip_set_elem_len(struct ip_set *set, struct nlattr *tb[],
-                             size_t len);
+                             size_t len, size_t align);
 extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
                                 struct ip_set_ext *ext);
 
index 187feabe557c379b2a78bb4467623722e7ed4996..5fcd375ef175b1a4e4870e99eb54d729a343b194 100644 (file)
@@ -5,10 +5,13 @@
 #include <linux/netdevice.h>
 
 #ifdef CONFIG_NETFILTER_INGRESS
-static inline int nf_hook_ingress_active(struct sk_buff *skb)
+static inline bool nf_hook_ingress_active(const struct sk_buff *skb)
 {
-       return nf_hook_list_active(&skb->dev->nf_hooks_ingress,
-                                  NFPROTO_NETDEV, NF_NETDEV_INGRESS);
+#ifdef HAVE_JUMP_LABEL
+       if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS]))
+               return false;
+#endif
+       return !list_empty(&skb->dev->nf_hooks_ingress);
 }
 
 static inline int nf_hook_ingress(struct sk_buff *skb)
@@ -16,8 +19,8 @@ static inline int nf_hook_ingress(struct sk_buff *skb)
        struct nf_hook_state state;
 
        nf_hook_state_init(&state, &skb->dev->nf_hooks_ingress,
-                          NF_NETDEV_INGRESS, INT_MIN, NFPROTO_NETDEV, NULL,
-                          skb->dev, NULL, dev_net(skb->dev), NULL);
+                          NF_NETDEV_INGRESS, INT_MIN, NFPROTO_NETDEV,
+                          skb->dev, NULL, NULL, dev_net(skb->dev), NULL);
        return nf_hook_slow(skb, &state);
 }
 
index 570d630f98ae53a34b4c9420f037d87c4b97a3cc..11bbae44f4cbf91dd3ed62aa9d2e1849b14a8839 100644 (file)
@@ -251,6 +251,7 @@ struct nfs4_layoutget {
        struct nfs4_layoutget_res res;
        struct rpc_cred *cred;
        gfp_t gfp_flags;
+       long timeout;
 };
 
 struct nfs4_getdeviceinfo_args {
index 36112cdd665a7f881693105e2cbfd4737e0a9881..b90d8ec57c1fb43fcc182b59e3d3267c79c68865 100644 (file)
@@ -80,7 +80,7 @@ static inline int of_dma_router_register(struct device_node *np,
 static inline struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                                                     const char *name)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
index 38c0533a33598bc8891af481589687c282739b37..2c51ee78b1c0e31074ee17eb9a341021ee3162e0 100644 (file)
@@ -16,7 +16,6 @@ int of_pci_get_devfn(struct device_node *np);
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
 int of_get_pci_domain_nr(struct device_node *node);
-void of_pci_dma_configure(struct pci_dev *pci_dev);
 void of_pci_check_probe_only(void);
 #else
 static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
@@ -53,8 +52,6 @@ of_get_pci_domain_nr(struct device_node *node)
        return -1;
 }
 
-static inline void of_pci_dma_configure(struct pci_dev *pci_dev) { }
-
 static inline void of_pci_check_probe_only(void) { }
 #endif
 
index e828e7b4afec67a4b9f083cfa65c2ff3cffe8571..6ae25aae88fd1254f40227341ca20b73a2e08ce2 100644 (file)
@@ -412,9 +412,18 @@ struct pci_host_bridge {
        void (*release_fn)(struct pci_host_bridge *);
        void *release_data;
        unsigned int ignore_reset_delay:1;      /* for entire hierarchy */
+       /* Resource alignment requirements */
+       resource_size_t (*align_resource)(struct pci_dev *dev,
+                       const struct resource *res,
+                       resource_size_t start,
+                       resource_size_t size,
+                       resource_size_t align);
 };
 
 #define        to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+
+struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
+
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
                     void (*release_fn)(struct pci_host_bridge *),
                     void *release_data);
index 463de52fe8915486d2e2159bde7edf12834f8dcc..0a3705a7c9f2a9cafeee00ab8d901b202d631c47 100644 (file)
@@ -27,6 +27,12 @@ enum dev_prop_type {
        DEV_PROP_MAX,
 };
 
+enum dev_dma_attr {
+       DEV_DMA_NOT_SUPPORTED,
+       DEV_DMA_NON_COHERENT,
+       DEV_DMA_COHERENT,
+};
+
 bool device_property_present(struct device *dev, const char *propname);
 int device_property_read_u8_array(struct device *dev, const char *propname,
                                  u8 *val, size_t nval);
@@ -168,7 +174,9 @@ struct property_set {
 
 void device_add_property_set(struct device *dev, struct property_set *pset);
 
-bool device_dma_is_coherent(struct device *dev);
+bool device_dma_supported(struct device *dev);
+
+enum dev_dma_attr device_get_dma_attr(struct device *dev);
 
 int device_get_phy_mode(struct device *dev);
 
index 80af3cd35ae4edf30dc05e1148cf8ee75033fcb3..72ce932c69b28b3bf240e9782d00c5555bf6a97d 100644 (file)
@@ -71,7 +71,7 @@ struct scpi_ops {
        int (*sensor_get_value)(u16, u32 *);
 };
 
-#if IS_ENABLED(CONFIG_ARM_SCPI_PROTOCOL)
+#if IS_REACHABLE(CONFIG_ARM_SCPI_PROTOCOL)
 struct scpi_ops *get_scpi_ops(void);
 #else
 static inline struct scpi_ops *get_scpi_ops(void) { return NULL; }
index ab1e0392b5ac1ce89c80dc2bf0e4e4ccc7a736bd..92557bbce7e7b9a3d9c6c6ed4c4d4f54ff7ff9e5 100644 (file)
@@ -239,7 +239,6 @@ extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern void set_current_blocked(sigset_t *);
 extern void __set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
-extern int sigsuspend(sigset_t *);
 
 struct sigaction {
 #ifndef __ARCH_HAS_IRIX_SIGACTION
index 7c82e3b307a332e27204b0d3316300d62f8990a0..2037a861e3679910152a98ba98a667b395c6773c 100644 (file)
@@ -157,6 +157,24 @@ size_t ksize(const void *);
 #define ARCH_KMALLOC_MINALIGN __alignof__(unsigned long long)
 #endif
 
+/*
+ * Setting ARCH_SLAB_MINALIGN in arch headers allows a different alignment.
+ * Intended for arches that get misalignment faults even for 64 bit integer
+ * aligned buffers.
+ */
+#ifndef ARCH_SLAB_MINALIGN
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+#endif
+
+/*
+ * kmalloc and friends return ARCH_KMALLOC_MINALIGN aligned
+ * pointers. kmem_cache_alloc and friends return ARCH_SLAB_MINALIGN
+ * aligned pointers.
+ */
+#define __assume_kmalloc_alignment __assume_aligned(ARCH_KMALLOC_MINALIGN)
+#define __assume_slab_alignment __assume_aligned(ARCH_SLAB_MINALIGN)
+#define __assume_page_alignment __assume_aligned(PAGE_SIZE)
+
 /*
  * Kmalloc array related definitions
  */
@@ -286,8 +304,8 @@ static __always_inline int kmalloc_index(size_t size)
 }
 #endif /* !CONFIG_SLOB */
 
-void *__kmalloc(size_t size, gfp_t flags);
-void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags);
+void *__kmalloc(size_t size, gfp_t flags) __assume_kmalloc_alignment;
+void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment;
 void kmem_cache_free(struct kmem_cache *, void *);
 
 /*
@@ -298,11 +316,11 @@ void kmem_cache_free(struct kmem_cache *, void *);
  * Note that interrupts must be enabled when calling these functions.
  */
 void kmem_cache_free_bulk(struct kmem_cache *, size_t, void **);
-bool kmem_cache_alloc_bulk(struct kmem_cache *, gfp_t, size_t, void **);
+int kmem_cache_alloc_bulk(struct kmem_cache *, gfp_t, size_t, void **);
 
 #ifdef CONFIG_NUMA
-void *__kmalloc_node(size_t size, gfp_t flags, int node);
-void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
+void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment;
+void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node) __assume_slab_alignment;
 #else
 static __always_inline void *__kmalloc_node(size_t size, gfp_t flags, int node)
 {
@@ -316,12 +334,12 @@ static __always_inline void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t f
 #endif
 
 #ifdef CONFIG_TRACING
-extern void *kmem_cache_alloc_trace(struct kmem_cache *, gfp_t, size_t);
+extern void *kmem_cache_alloc_trace(struct kmem_cache *, gfp_t, size_t) __assume_slab_alignment;
 
 #ifdef CONFIG_NUMA
 extern void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
                                           gfp_t gfpflags,
-                                          int node, size_t size);
+                                          int node, size_t size) __assume_slab_alignment;
 #else
 static __always_inline void *
 kmem_cache_alloc_node_trace(struct kmem_cache *s,
@@ -354,10 +372,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 }
 #endif /* CONFIG_TRACING */
 
-extern void *kmalloc_order(size_t size, gfp_t flags, unsigned int order);
+extern void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) __assume_page_alignment;
 
 #ifdef CONFIG_TRACING
-extern void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order);
+extern void *kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order) __assume_page_alignment;
 #else
 static __always_inline void *
 kmalloc_order_trace(size_t size, gfp_t flags, unsigned int order)
@@ -482,15 +500,6 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
        return __kmalloc_node(size, flags, node);
 }
 
-/*
- * Setting ARCH_SLAB_MINALIGN in arch headers allows a different alignment.
- * Intended for arches that get misalignment faults even for 64 bit integer
- * aligned buffers.
- */
-#ifndef ARCH_SLAB_MINALIGN
-#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
-#endif
-
 struct memcg_cache_array {
        struct rcu_head rcu;
        struct kmem_cache *entries[0];
index a156b82dd14cbad0b6f2867d07fc883fbc685c1e..c2b66a277e9807de8a224879793c121df63f7d69 100644 (file)
@@ -524,7 +524,7 @@ asmlinkage long sys_chown(const char __user *filename,
 asmlinkage long sys_lchown(const char __user *filename,
                                uid_t user, gid_t group);
 asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
-#ifdef CONFIG_UID16
+#ifdef CONFIG_HAVE_UID16
 asmlinkage long sys_chown16(const char __user *filename,
                                old_uid_t user, old_gid_t group);
 asmlinkage long sys_lchown16(const char __user *filename,
index ea090eaf468c6337b5ad29685b0d4919e44d2fab..c6f0f0d0e17e07609a8f6ae493bd71bdef093676 100644 (file)
@@ -64,10 +64,18 @@ do {                                                        \
  *             a new subdirectory with this name.
  * @is_visible:        Optional: Function to return permissions associated with an
  *             attribute of the group. Will be called repeatedly for each
- *             attribute in the group. Only read/write permissions as well as
- *             SYSFS_PREALLOC are accepted. Must return 0 if an attribute is
- *             not visible. The returned value will replace static permissions
- *             defined in struct attribute or struct bin_attribute.
+ *             non-binary attribute in the group. Only read/write
+ *             permissions as well as SYSFS_PREALLOC are accepted. Must
+ *             return 0 if an attribute is not visible. The returned value
+ *             will replace static permissions defined in struct attribute.
+ * @is_bin_visible:
+ *             Optional: Function to return permissions associated with a
+ *             binary attribute of the group. Will be called repeatedly
+ *             for each binary attribute in the group. Only read/write
+ *             permissions as well as SYSFS_PREALLOC are accepted. Must
+ *             return 0 if a binary attribute is not visible. The returned
+ *             value will replace static permissions defined in
+ *             struct bin_attribute.
  * @attrs:     Pointer to NULL terminated list of attributes.
  * @bin_attrs: Pointer to NULL terminated list of binary attributes.
  *             Either attrs or bin_attrs or both must be provided.
@@ -76,6 +84,8 @@ struct attribute_group {
        const char              *name;
        umode_t                 (*is_visible)(struct kobject *,
                                              struct attribute *, int);
+       umode_t                 (*is_bin_visible)(struct kobject *,
+                                                 struct bin_attribute *, int);
        struct attribute        **attrs;
        struct bin_attribute    **bin_attrs;
 };
index 5b04b0a5375b338dabbfa4a68b8482e04ffbbbc9..5e31f1b99037d3cc1d43d2336886a8dcb435808f 100644 (file)
@@ -607,7 +607,7 @@ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
 
 /* tty_audit.c */
 #ifdef CONFIG_AUDIT
-extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+extern void tty_audit_add_data(struct tty_struct *tty, const void *data,
                               size_t size, unsigned icanon);
 extern void tty_audit_exit(void);
 extern void tty_audit_fork(struct signal_struct *sig);
@@ -615,8 +615,8 @@ extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
 extern void tty_audit_push(struct tty_struct *tty);
 extern int tty_audit_push_current(void);
 #else
-static inline void tty_audit_add_data(struct tty_struct *tty,
-               unsigned char *data, size_t size, unsigned icanon)
+static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
+                                     size_t size, unsigned icanon)
 {
 }
 static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
index 70d8500bddf15e9c68bc5149b29c487e28e5f201..70dd3dfde6319e661069f6b8c2d5a6b15804f27f 100644 (file)
@@ -35,7 +35,7 @@ typedef __kernel_gid16_t        gid16_t;
 
 typedef unsigned long          uintptr_t;
 
-#ifdef CONFIG_UID16
+#ifdef CONFIG_HAVE_UID16
 /* This is defined by include/asm-{arch}/posix_types.h */
 typedef __kernel_old_uid_t     old_uid_t;
 typedef __kernel_old_gid_t     old_gid_t;
index d74c0ae989d501d4d50af2cd974595f49632b3dc..c36e95730de14d577e2a84962dc1c9fa2694f27a 100644 (file)
@@ -7,9 +7,10 @@ int check_user_usb_string(const char *name,
                struct usb_gadget_strings *stringtab_dev);
 
 #define GS_STRINGS_W(__struct, __name) \
-       static ssize_t __struct##_##__name##_store(struct __struct *gs, \
+static ssize_t __struct##_##__name##_store(struct config_item *item, \
                const char *page, size_t len)           \
 {                                                      \
+       struct __struct *gs = to_##__struct(item);      \
        int ret;                                        \
                                                        \
        ret = usb_string_copy(page, &gs->__name);       \
@@ -19,30 +20,20 @@ int check_user_usb_string(const char *name,
 }
 
 #define GS_STRINGS_R(__struct, __name) \
-       static ssize_t __struct##_##__name##_show(struct __struct *gs, \
-                       char *page)     \
+static ssize_t __struct##_##__name##_show(struct config_item *item, char *page) \
 {      \
+       struct __struct *gs = to_##__struct(item);      \
        return sprintf(page, "%s\n", gs->__name ?: ""); \
 }
 
-#define GS_STRING_ITEM_ATTR(struct_name, name) \
-       static struct struct_name##_attribute struct_name##_##name = \
-               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
-                               struct_name##_##name##_show,            \
-                               struct_name##_##name##_store)
-
 #define GS_STRINGS_RW(struct_name, _name)      \
        GS_STRINGS_R(struct_name, _name)        \
        GS_STRINGS_W(struct_name, _name)        \
-       GS_STRING_ITEM_ATTR(struct_name, _name)
+       CONFIGFS_ATTR(struct_name##_, _name)
 
 #define USB_CONFIG_STRING_RW_OPS(struct_in)                            \
-       CONFIGFS_ATTR_OPS(struct_in);                                   \
-                                                                       \
 static struct configfs_item_operations struct_in##_langid_item_ops = { \
        .release                = struct_in##_attr_release,             \
-       .show_attribute         = struct_in##_attr_show,                \
-       .store_attribute        = struct_in##_attr_store,               \
 };                                                                     \
                                                                        \
 static struct config_item_type struct_in##_langid_type = {             \
index ddb44097538245f17e882efff635143ada49e089..610a86a892b8896363ece505cdbe686096505cfc 100644 (file)
@@ -44,6 +44,9 @@ struct vfio_device_ops {
        void    (*request)(void *device_data, unsigned int count);
 };
 
+extern struct iommu_group *vfio_iommu_group_get(struct device *dev);
+extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev);
+
 extern int vfio_add_group_dev(struct device *dev,
                              const struct vfio_device_ops *ops,
                              void *device_data);
index 91b0a68d38dc2a4941c1b36a8cac270af0136422..89474b9d260cf44151b21e26ce5d64aecf62b6cb 100644 (file)
@@ -21,15 +21,19 @@ struct dentry;
 
 struct xattr_handler {
        const char *prefix;
-       int flags;      /* fs private flags passed back to the handlers */
-       size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
-                      const char *name, size_t name_len, int handler_flags);
-       int (*get)(struct dentry *dentry, const char *name, void *buffer,
-                  size_t size, int handler_flags);
-       int (*set)(struct dentry *dentry, const char *name, const void *buffer,
-                  size_t size, int flags, int handler_flags);
+       int flags;      /* fs private flags */
+       size_t (*list)(const struct xattr_handler *, struct dentry *dentry,
+                      char *list, size_t list_size, const char *name,
+                      size_t name_len);
+       int (*get)(const struct xattr_handler *, struct dentry *dentry,
+                  const char *name, void *buffer, size_t size);
+       int (*set)(const struct xattr_handler *, struct dentry *dentry,
+                  const char *name, const void *buffer, size_t size,
+                  int flags);
 };
 
+const char *xattr_full_name(const struct xattr_handler *, const char *);
+
 struct xattr {
        const char *name;
        void *value;
index aaf9700fc9e5f8279a172a7ee447cf4f9b5b6ffe..fb961a576abe4a62d02c69d6393abd91a2930fe1 100644 (file)
@@ -167,7 +167,8 @@ static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
 
 static inline u32 rt6_get_cookie(const struct rt6_info *rt)
 {
-       if (rt->rt6i_flags & RTF_PCPU || unlikely(rt->dst.flags & DST_NOCACHE))
+       if (rt->rt6i_flags & RTF_PCPU ||
+           (unlikely(rt->dst.flags & DST_NOCACHE) && rt->dst.from))
                rt = (struct rt6_info *)(rt->dst.from);
 
        return rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
index aaee6fa02cf1d2a756eb6b97559501c47af1c635..ff788b665277d59d8039fd4588f3e0256639833c 100644 (file)
@@ -90,11 +90,12 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
        err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
 
        if (net_xmit_eval(err) == 0) {
-               struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
+               struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->tx_bytes += pkt_len;
                tstats->tx_packets++;
                u64_stats_update_end(&tstats->syncp);
+               put_cpu_ptr(tstats);
        } else {
                stats->tx_errors++;
                stats->tx_aborted_errors++;
index f6dafec9102c5f03e08fdd7fc3efc4812e4137ce..62a750a6a8f8cb32c9eb5d8d160aa94a20898473 100644 (file)
@@ -287,12 +287,13 @@ static inline void iptunnel_xmit_stats(int err,
                                       struct pcpu_sw_netstats __percpu *stats)
 {
        if (err > 0) {
-               struct pcpu_sw_netstats *tstats = this_cpu_ptr(stats);
+               struct pcpu_sw_netstats *tstats = get_cpu_ptr(stats);
 
                u64_stats_update_begin(&tstats->syncp);
                tstats->tx_bytes += err;
                tstats->tx_packets++;
                u64_stats_update_end(&tstats->syncp);
+               put_cpu_ptr(tstats);
        } else if (err < 0) {
                err_stats->tx_errors++;
                err_stats->tx_aborted_errors++;
index c9149cc0a02d30683288de140bc3276d75e640ce..4bd7508bedc9fefb08c8e3a8cd65278553c4412c 100644 (file)
@@ -618,6 +618,8 @@ struct nft_expr_ops {
        void                            (*eval)(const struct nft_expr *expr,
                                                struct nft_regs *regs,
                                                const struct nft_pktinfo *pkt);
+       int                             (*clone)(struct nft_expr *dst,
+                                                const struct nft_expr *src);
        unsigned int                    size;
 
        int                             (*init)(const struct nft_ctx *ctx,
@@ -660,10 +662,20 @@ void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
 int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
                  const struct nft_expr *expr);
 
-static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
+static inline int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
 {
+       int err;
+
        __module_get(src->ops->type->owner);
-       memcpy(dst, src, src->ops->size);
+       if (src->ops->clone) {
+               dst->ops = src->ops;
+               err = src->ops->clone(dst, src);
+               if (err < 0)
+                       return err;
+       } else {
+               memcpy(dst, src, src->ops->size);
+       }
+       return 0;
 }
 
 /**
index bbf7c2cf15b4ec278bca5426b3319ca501454d66..7f89e4ba18d11ee6a9261edf85cac743d9f8d5ea 100644 (file)
@@ -2226,6 +2226,31 @@ static inline bool sk_listener(const struct sock *sk)
        return (1 << sk->sk_state) & (TCPF_LISTEN | TCPF_NEW_SYN_RECV);
 }
 
+/**
+ * sk_state_load - read sk->sk_state for lockless contexts
+ * @sk: socket pointer
+ *
+ * Paired with sk_state_store(). Used in places we do not hold socket lock :
+ * tcp_diag_get_info(), tcp_get_info(), tcp_poll(), get_tcp4_sock() ...
+ */
+static inline int sk_state_load(const struct sock *sk)
+{
+       return smp_load_acquire(&sk->sk_state);
+}
+
+/**
+ * sk_state_store - update sk->sk_state
+ * @sk: socket pointer
+ * @newstate: new state
+ *
+ * Paired with sk_state_load(). Should be used in contexts where
+ * state change might impact lockless readers.
+ */
+static inline void sk_state_store(struct sock *sk, int newstate)
+{
+       smp_store_release(&sk->sk_state, newstate);
+}
+
 void sock_enable_timestamp(struct sock *sk, int flag);
 int sock_get_timestamp(struct sock *, struct timeval __user *);
 int sock_get_timestampns(struct sock *, struct timespec __user *);
index bc865e244efea0c4757a182274ad7ca9f9cc3266..1d22ce9f352e2e7610095c4b1774164aa6af4516 100644 (file)
@@ -323,7 +323,7 @@ static inline int switchdev_port_fdb_dump(struct sk_buff *skb,
                                          struct net_device *filter_dev,
                                          int idx)
 {
-       return -EOPNOTSUPP;
+       return idx;
 }
 
 static inline void switchdev_port_fwd_mark_set(struct net_device *dev,
index e113c757d555ef097954a4b41137f4d4b5a8f4e1..ed527121031dd31b424c1ff596f9139cfcdefd02 100644 (file)
@@ -405,11 +405,6 @@ struct scsi_host_template {
        /* If use block layer to manage tags, this is tag allocation policy */
        int tag_alloc_policy;
 
-       /*
-        * Let the block layer assigns tags to all commands.
-        */
-       unsigned use_blk_tags:1;
-
        /*
         * Track QUEUE_FULL events and reduce queue depth on demand.
         */
index b27977e8aaed9b12bf6497fbdf01879a47b26cbc..4416b1026189c182bb75fbc5f677f587007522a7 100644 (file)
 
 
 #ifdef CONFIG_BLOCK
-static inline struct scsi_cmnd *scsi_mq_find_tag(struct Scsi_Host *shost,
-                                                int unique_tag)
-{
-       u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag);
-       struct request *req = NULL;
-
-       if (hwq < shost->tag_set.nr_hw_queues)
-               req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
-                                      blk_mq_unique_tag_to_tag(unique_tag));
-       return req ? (struct scsi_cmnd *)req->special : NULL;
-}
-
-/**
- * scsi_find_tag - find a tagged command by device
- * @SDpnt:     pointer to the ScSI device
- * @tag:       tag generated by blk_mq_unique_tag()
- *
- * Notes:
- *     Only works with tags allocated by the generic blk layer.
- **/
-static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
-{
-        struct request *req;
-
-        if (tag != SCSI_NO_TAG) {
-               if (shost_use_blk_mq(sdev->host))
-                       return scsi_mq_find_tag(sdev->host, tag);
-
-               req = blk_queue_find_tag(sdev->request_queue, tag);
-               return req ? (struct scsi_cmnd *)req->special : NULL;
-       }
-
-       /* single command, look in space */
-       return sdev->current_cmnd;
-}
-
-
-/**
- * scsi_init_shared_tag_map - create a shared tag map
- * @shost:     the host to share the tag map among all devices
- * @depth:     the total depth of the map
- */
-static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
-{
-       /*
-        * We always have a shared tag map around when using blk-mq.
-        */
-       if (shost_use_blk_mq(shost))
-               return 0;
-
-       /*
-        * If the shared tag map isn't already initialized, do it now.
-        * This saves callers from having to check ->bqt when setting up
-        * devices on the shared host (for libata)
-        */
-       if (!shost->bqt) {
-               shost->bqt = blk_init_tags(depth,
-                       shost->hostt->tag_alloc_policy);
-               if (!shost->bqt)
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 /**
  * scsi_host_find_tag - find the tagged command by host
  * @shost:     pointer to scsi_host
- * @tag:       tag generated by blk_mq_unique_tag()
+ * @tag:       tag
  *
- * Notes:
- *     Only works with tags allocated by the generic blk layer.
+ * Note: for devices using multiple hardware queues tag must have been
+ * generated by blk_mq_unique_tag().
  **/
 static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost,
-                                               int tag)
+               int tag)
 {
-       struct request *req;
+       struct request *req = NULL;
 
-       if (tag != SCSI_NO_TAG) {
-               if (shost_use_blk_mq(shost))
-                       return scsi_mq_find_tag(shost, tag);
+       if (tag == SCSI_NO_TAG)
+               return NULL;
+
+       if (shost_use_blk_mq(shost)) {
+               u16 hwq = blk_mq_unique_tag_to_hwq(tag);
+
+               if (hwq < shost->tag_set.nr_hw_queues) {
+                       req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
+                               blk_mq_unique_tag_to_tag(tag));
+               }
+       } else {
                req = blk_map_queue_find_tag(shost->bqt, tag);
-               return req ? (struct scsi_cmnd *)req->special : NULL;
        }
-       return NULL;
+
+       if (!req)
+               return NULL;
+       return req->special;
 }
 
 #endif /* CONFIG_BLOCK */
diff --git a/include/target/configfs_macros.h b/include/target/configfs_macros.h
deleted file mode 100644 (file)
index a0fc85b..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * configfs_macros.h - extends macros for configfs
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 021110-1307, USA.
- *
- * Based on sysfs:
- *     sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
- *
- * Based on kobject.h:
- *      Copyright (c) 2002-2003        Patrick Mochel
- *      Copyright (c) 2002-2003        Open Source Development Labs
- *
- * configfs Copyright (C) 2005 Oracle.  All rights reserved.
- *
- * Added CONFIGFS_EATTR() macros from original configfs.h macros
- * Copright (C) 2008-2009 Nicholas A. Bellinger <nab@linux-iscsi.org>
- *
- * Please read Documentation/filesystems/configfs/configfs.txt before using
- * the configfs interface, ESPECIALLY the parts about reference counts and
- * item destructors.
- */
-
-#ifndef _CONFIGFS_MACROS_H_
-#define _CONFIGFS_MACROS_H_
-
-#include <linux/configfs.h>
-
-/*
- * Users often need to create attribute structures for their configurable
- * attributes, containing a configfs_attribute member and function pointers
- * for the show() and store() operations on that attribute. If they don't
- * need anything else on the extended attribute structure, they can use
- * this macro to define it.  The argument _name isends up as
- * 'struct _name_attribute, as well as names of to CONFIGFS_ATTR_OPS() below.
- * The argument _item is the name of the structure containing the
- * struct config_item or struct config_group structure members
- */
-#define CONFIGFS_EATTR_STRUCT(_name, _item)                            \
-struct _name##_attribute {                                             \
-       struct configfs_attribute attr;                                 \
-       ssize_t (*show)(struct _item *, char *);                        \
-       ssize_t (*store)(struct _item *, const char *, size_t);         \
-}
-
-/*
- * With the extended attribute structure, users can use this macro
- * (similar to sysfs' __ATTR) to make defining attributes easier.
- * An example:
- * #define MYITEM_EATTR(_name, _mode, _show, _store)   \
- * struct myitem_attribute childless_attr_##_name =    \
- *         __CONFIGFS_EATTR(_name, _mode, _show, _store)
- */
-#define __CONFIGFS_EATTR(_name, _mode, _show, _store)                  \
-{                                                                      \
-       .attr   = {                                                     \
-                       .ca_name = __stringify(_name),                  \
-                       .ca_mode = _mode,                               \
-                       .ca_owner = THIS_MODULE,                        \
-       },                                                              \
-       .show   = _show,                                                \
-       .store  = _store,                                               \
-}
-/* Here is a readonly version, only requiring a show() operation */
-#define __CONFIGFS_EATTR_RO(_name, _show)                              \
-{                                                                      \
-       .attr   = {                                                     \
-                       .ca_name = __stringify(_name),                  \
-                       .ca_mode = 0444,                                \
-                       .ca_owner = THIS_MODULE,                        \
-       },                                                              \
-       .show   = _show,                                                \
-}
-
-/*
- * With these extended attributes, the simple show_attribute() and
- * store_attribute() operations need to call the show() and store() of the
- * attributes.  This is a common pattern, so we provide a macro to define
- * them.  The argument _name is the name of the attribute defined by
- * CONFIGFS_ATTR_STRUCT(). The argument _item is the name of the structure
- * containing the struct config_item or struct config_group structure member.
- * The argument _item_member is the actual name of the struct config_* struct
- * in your _item structure.  Meaning  my_structure->some_config_group.
- *                                   ^^_item^^^^^  ^^_item_member^^^
- * This macro expects the attributes to be named "struct <name>_attribute".
- */
-#define CONFIGFS_EATTR_OPS_TO_FUNC(_name, _item, _item_member)         \
-static struct _item *to_##_name(struct config_item *ci)                        \
-{                                                                      \
-       return (ci) ? container_of(to_config_group(ci), struct _item,   \
-               _item_member) : NULL;                                   \
-}
-
-#define CONFIGFS_EATTR_OPS_SHOW(_name, _item)                          \
-static ssize_t _name##_attr_show(struct config_item *item,             \
-                                struct configfs_attribute *attr,       \
-                                char *page)                            \
-{                                                                      \
-       struct _item *_item = to_##_name(item);                         \
-       struct _name##_attribute * _name##_attr =                       \
-               container_of(attr, struct _name##_attribute, attr);     \
-       ssize_t ret = 0;                                                \
-                                                                       \
-       if (_name##_attr->show)                                         \
-               ret = _name##_attr->show(_item, page);                  \
-       return ret;                                                     \
-}
-
-#define CONFIGFS_EATTR_OPS_STORE(_name, _item)                         \
-static ssize_t _name##_attr_store(struct config_item *item,            \
-                                 struct configfs_attribute *attr,      \
-                                 const char *page, size_t count)       \
-{                                                                      \
-       struct _item *_item = to_##_name(item);                         \
-       struct _name##_attribute * _name##_attr =                       \
-               container_of(attr, struct _name##_attribute, attr);     \
-       ssize_t ret = -EINVAL;                                          \
-                                                                       \
-       if (_name##_attr->store)                                        \
-               ret = _name##_attr->store(_item, page, count);          \
-       return ret;                                                     \
-}
-
-#define CONFIGFS_EATTR_OPS(_name, _item, _item_member)                 \
-       CONFIGFS_EATTR_OPS_TO_FUNC(_name, _item, _item_member);         \
-       CONFIGFS_EATTR_OPS_SHOW(_name, _item);                          \
-       CONFIGFS_EATTR_OPS_STORE(_name, _item);
-
-#define CONFIGFS_EATTR_OPS_RO(_name, _item, _item_member)              \
-       CONFIGFS_EATTR_OPS_TO_FUNC(_name, _item, _item_member);         \
-       CONFIGFS_EATTR_OPS_SHOW(_name, _item);
-
-#endif /* _CONFIGFS_MACROS_H_ */
index 5f48754dc36ae0e15e06527c0cb63dc29324721e..0a2c74008e5388f6d817272735882f40abc3a013 100644 (file)
@@ -563,6 +563,36 @@ struct se_node_acl {
        struct kref             acl_kref;
 };
 
+static inline struct se_node_acl *acl_to_nacl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_node_acl,
+                       acl_group);
+}
+
+static inline struct se_node_acl *attrib_to_nacl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_node_acl,
+                       acl_attrib_group);
+}
+
+static inline struct se_node_acl *auth_to_nacl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_node_acl,
+                       acl_auth_group);
+}
+
+static inline struct se_node_acl *param_to_nacl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_node_acl,
+                       acl_param_group);
+}
+
+static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_node_acl,
+                       acl_fabric_stat_group);
+}
+
 struct se_session {
        unsigned                sess_tearing_down:1;
        u64                     sess_bin_isid;
@@ -821,6 +851,12 @@ struct se_tpg_np {
        struct config_group     tpg_np_group;
 };
 
+static inline struct se_tpg_np *to_tpg_np(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_tpg_np,
+                       tpg_np_group);
+}
+
 struct se_portal_group {
        /*
         * PROTOCOL IDENTIFIER value per SPC4, 7.5.1.
@@ -857,6 +893,30 @@ struct se_portal_group {
        struct config_group     tpg_param_group;
 };
 
+static inline struct se_portal_group *to_tpg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_portal_group,
+                       tpg_group);
+}
+
+static inline struct se_portal_group *attrib_to_tpg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_portal_group,
+                       tpg_attrib_group);
+}
+
+static inline struct se_portal_group *auth_to_tpg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_portal_group,
+                       tpg_auth_group);
+}
+
+static inline struct se_portal_group *param_to_tpg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct se_portal_group,
+                       tpg_param_group);
+}
+
 struct se_wwn {
        struct target_fabric_configfs *wwn_tf;
        struct config_group     wwn_group;
diff --git a/include/target/target_core_fabric_configfs.h b/include/target/target_core_fabric_configfs.h
deleted file mode 100644 (file)
index 7a0649c..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Used for tfc_wwn_cit attributes
- */
-
-#include <target/configfs_macros.h>
-
-CONFIGFS_EATTR_STRUCT(target_fabric_nacl_attrib, se_node_acl);
-#define TF_NACL_ATTRIB_ATTR(_fabric, _name, _mode)                     \
-static struct target_fabric_nacl_attrib_attribute _fabric##_nacl_attrib_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_nacl_attrib_show_##_name,                             \
-       _fabric##_nacl_attrib_store_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_nacl_auth, se_node_acl);
-#define TF_NACL_AUTH_ATTR(_fabric, _name, _mode)                       \
-static struct target_fabric_nacl_auth_attribute _fabric##_nacl_auth_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_nacl_auth_show_##_name,                               \
-       _fabric##_nacl_auth_store_##_name);
-
-#define TF_NACL_AUTH_ATTR_RO(_fabric, _name)                           \
-static struct target_fabric_nacl_auth_attribute _fabric##_nacl_auth_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_nacl_auth_show_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_nacl_param, se_node_acl);
-#define TF_NACL_PARAM_ATTR(_fabric, _name, _mode)                      \
-static struct target_fabric_nacl_param_attribute _fabric##_nacl_param_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_nacl_param_show_##_name,                              \
-       _fabric##_nacl_param_store_##_name);
-
-#define TF_NACL_PARAM_ATTR_RO(_fabric, _name)                          \
-static struct target_fabric_nacl_param_attribute _fabric##_nacl_param_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_nacl_param_show_##_name);
-
-
-CONFIGFS_EATTR_STRUCT(target_fabric_nacl_base, se_node_acl);
-#define TF_NACL_BASE_ATTR(_fabric, _name, _mode)                       \
-static struct target_fabric_nacl_base_attribute _fabric##_nacl_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_nacl_show_##_name,                                    \
-       _fabric##_nacl_store_##_name);
-
-#define TF_NACL_BASE_ATTR_RO(_fabric, _name)                           \
-static struct target_fabric_nacl_base_attribute _fabric##_nacl_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_nacl_show_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_np_base, se_tpg_np);
-#define TF_NP_BASE_ATTR(_fabric, _name, _mode)                         \
-static struct target_fabric_np_base_attribute _fabric##_np_##_name =   \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_np_show_##_name,                                      \
-       _fabric##_np_store_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_tpg_attrib, se_portal_group);
-#define TF_TPG_ATTRIB_ATTR(_fabric, _name, _mode)                      \
-static struct target_fabric_tpg_attrib_attribute _fabric##_tpg_attrib_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_tpg_attrib_show_##_name,                              \
-       _fabric##_tpg_attrib_store_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_tpg_auth, se_portal_group);
-#define TF_TPG_AUTH_ATTR(_fabric, _name, _mode)                        \
-static struct target_fabric_tpg_auth_attribute _fabric##_tpg_auth_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_tpg_auth_show_##_name,                                \
-       _fabric##_tpg_auth_store_##_name);
-
-#define TF_TPG_AUTH_ATTR_RO(_fabric, _name)                            \
-static struct target_fabric_tpg_auth_attribute _fabric##_tpg_auth_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_tpg_auth_show_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_tpg_param, se_portal_group);
-#define TF_TPG_PARAM_ATTR(_fabric, _name, _mode)                       \
-static struct target_fabric_tpg_param_attribute _fabric##_tpg_param_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_tpg_param_show_##_name,                               \
-       _fabric##_tpg_param_store_##_name);
-
-
-CONFIGFS_EATTR_STRUCT(target_fabric_tpg, se_portal_group);
-#define TF_TPG_BASE_ATTR(_fabric, _name, _mode)                                \
-static struct target_fabric_tpg_attribute _fabric##_tpg_##_name =      \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_tpg_show_##_name,                                     \
-       _fabric##_tpg_store_##_name);
-
-
-#define TF_TPG_BASE_ATTR_RO(_fabric, _name)                            \
-static struct target_fabric_tpg_attribute _fabric##_tpg_##_name =      \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_tpg_show_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_wwn, target_fabric_configfs);
-#define TF_WWN_ATTR(_fabric, _name, _mode)                             \
-static struct target_fabric_wwn_attribute _fabric##_wwn_##_name =      \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_wwn_show_attr_##_name,                                \
-       _fabric##_wwn_store_attr_##_name);
-
-#define TF_WWN_ATTR_RO(_fabric, _name)                                 \
-static struct target_fabric_wwn_attribute _fabric##_wwn_##_name =      \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_wwn_show_attr_##_name);
-
-CONFIGFS_EATTR_STRUCT(target_fabric_discovery, target_fabric_configfs);
-#define TF_DISC_ATTR(_fabric, _name, _mode)                            \
-static struct target_fabric_discovery_attribute _fabric##_disc_##_name = \
-       __CONFIGFS_EATTR(_name, _mode,                                  \
-       _fabric##_disc_show_##_name,                                    \
-       _fabric##_disc_store_##_name);
-
-#define TF_DISC_ATTR_RO(_fabric, _name)                                        \
-static struct target_fabric_discovery_attribute _fabric##_disc_##_name = \
-       __CONFIGFS_EATTR_RO(_name,                                      \
-       _fabric##_disc_show_##_name);
-
-extern int target_fabric_setup_cits(struct target_fabric_configfs *);
index 8c5e8b91a3cbbb6b35542e57b64365b608c4073b..0b69a7753558ff27a07748f2d5ca7f3f054b2ba2 100644 (file)
 /* add more to the end as needed */
 
 #define fourcc_mod_code(vendor, val) \
-       ((((u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
+       ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
 
 /*
  * Format Modifier tokens:
index 654bae3f1a389a4fcff05ba6098fcdd6d6b3204a..5e6296160361cc7b7a7b9d80411ef172c3a453c7 100644 (file)
 
 #define NFS_PIPE_DIRNAME "nfs"
 
-/* NFS ioctls */
-/* Let's follow btrfs lead on CLONE to avoid messing userspace */
-#define NFS_IOC_CLONE          _IOW(0x94, 9, int)
-#define NFS_IOC_CLONE_RANGE    _IOW(0x94, 13, int)
-
-struct nfs_ioctl_clone_range_args {
-       __s64 src_fd;
-       __u64 src_off, count;
-       __u64 dst_off;
-};
-
 /*
  * NFS stats. The good thing with these values is that NFSv3 errors are
  * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which
index 9fd7b5d8df2fa357f434a899cccfa7810f826107..751b69f858c80411c910f21db7fb50c8902e94cf 100644 (file)
 
 #define VFIO_SPAPR_TCE_v2_IOMMU                7
 
+/*
+ * The No-IOMMU IOMMU offers no translation or isolation for devices and
+ * supports no ioctls outside of VFIO_CHECK_EXTENSION.  Use of VFIO's No-IOMMU
+ * code will taint the host kernel and should be used with extreme caution.
+ */
+#define VFIO_NOIOMMU_IOMMU             8
+
 /*
  * The IOCTL interface is designed for extensibility by embedding the
  * structure length (argsz) and flags into structures passed between
index 0a495ab35bc72b55d8eab13f0922e6fdb8099d9a..d8560ee3bab788c15be6d1be8eb610473fc5c4b5 100644 (file)
@@ -58,36 +58,13 @@ static void context_tracking_recursion_exit(void)
  * instructions to execute won't use any RCU read side critical section
  * because this function sets RCU in extended quiescent state.
  */
-void context_tracking_enter(enum ctx_state state)
+void __context_tracking_enter(enum ctx_state state)
 {
-       unsigned long flags;
-
-       /*
-        * Repeat the user_enter() check here because some archs may be calling
-        * this from asm and if no CPU needs context tracking, they shouldn't
-        * go further. Repeat the check here until they support the inline static
-        * key check.
-        */
-       if (!context_tracking_is_enabled())
-               return;
-
-       /*
-        * Some contexts may involve an exception occuring in an irq,
-        * leading to that nesting:
-        * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
-        * This would mess up the dyntick_nesting count though. And rcu_irq_*()
-        * helpers are enough to protect RCU uses inside the exception. So
-        * just return immediately if we detect we are in an IRQ.
-        */
-       if (in_interrupt())
-               return;
-
        /* Kernel threads aren't supposed to go to userspace */
        WARN_ON_ONCE(!current->mm);
 
-       local_irq_save(flags);
        if (!context_tracking_recursion_enter())
-               goto out_irq_restore;
+               return;
 
        if ( __this_cpu_read(context_tracking.state) != state) {
                if (__this_cpu_read(context_tracking.active)) {
@@ -120,7 +97,27 @@ void context_tracking_enter(enum ctx_state state)
                __this_cpu_write(context_tracking.state, state);
        }
        context_tracking_recursion_exit();
-out_irq_restore:
+}
+NOKPROBE_SYMBOL(__context_tracking_enter);
+EXPORT_SYMBOL_GPL(__context_tracking_enter);
+
+void context_tracking_enter(enum ctx_state state)
+{
+       unsigned long flags;
+
+       /*
+        * Some contexts may involve an exception occuring in an irq,
+        * leading to that nesting:
+        * rcu_irq_enter() rcu_user_exit() rcu_user_exit() rcu_irq_exit()
+        * This would mess up the dyntick_nesting count though. And rcu_irq_*()
+        * helpers are enough to protect RCU uses inside the exception. So
+        * just return immediately if we detect we are in an IRQ.
+        */
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+       __context_tracking_enter(state);
        local_irq_restore(flags);
 }
 NOKPROBE_SYMBOL(context_tracking_enter);
@@ -128,7 +125,7 @@ EXPORT_SYMBOL_GPL(context_tracking_enter);
 
 void context_tracking_user_enter(void)
 {
-       context_tracking_enter(CONTEXT_USER);
+       user_enter();
 }
 NOKPROBE_SYMBOL(context_tracking_user_enter);
 
@@ -144,19 +141,10 @@ NOKPROBE_SYMBOL(context_tracking_user_enter);
  * This call supports re-entrancy. This way it can be called from any exception
  * handler without needing to know if we came from userspace or not.
  */
-void context_tracking_exit(enum ctx_state state)
+void __context_tracking_exit(enum ctx_state state)
 {
-       unsigned long flags;
-
-       if (!context_tracking_is_enabled())
-               return;
-
-       if (in_interrupt())
-               return;
-
-       local_irq_save(flags);
        if (!context_tracking_recursion_enter())
-               goto out_irq_restore;
+               return;
 
        if (__this_cpu_read(context_tracking.state) == state) {
                if (__this_cpu_read(context_tracking.active)) {
@@ -173,7 +161,19 @@ void context_tracking_exit(enum ctx_state state)
                __this_cpu_write(context_tracking.state, CONTEXT_KERNEL);
        }
        context_tracking_recursion_exit();
-out_irq_restore:
+}
+NOKPROBE_SYMBOL(__context_tracking_exit);
+EXPORT_SYMBOL_GPL(__context_tracking_exit);
+
+void context_tracking_exit(enum ctx_state state)
+{
+       unsigned long flags;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+       __context_tracking_exit(state);
        local_irq_restore(flags);
 }
 NOKPROBE_SYMBOL(context_tracking_exit);
@@ -181,7 +181,7 @@ EXPORT_SYMBOL_GPL(context_tracking_exit);
 
 void context_tracking_user_exit(void)
 {
-       context_tracking_exit(CONTEXT_USER);
+       user_exit();
 }
 NOKPROBE_SYMBOL(context_tracking_user_exit);
 
index 1a734e0adfa78259dac6cae57239a2d5f992a9ac..36babfd2064842c28d4951a656ea1e84500bbf8f 100644 (file)
@@ -1050,13 +1050,13 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
        /*
         * One of the few rules of preemptible RCU is that one cannot do
         * rcu_read_unlock() while holding a scheduler (or nested) lock when
-        * part of the read side critical section was preemptible -- see
+        * part of the read side critical section was irqs-enabled -- see
         * rcu_read_unlock_special().
         *
         * Since ctx->lock nests under rq->lock we must ensure the entire read
-        * side critical section is non-preemptible.
+        * side critical section has interrupts disabled.
         */
-       preempt_disable();
+       local_irq_save(*flags);
        rcu_read_lock();
        ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
        if (ctx) {
@@ -1070,21 +1070,22 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
                 * if so.  If we locked the right context, then it
                 * can't get swapped on us any more.
                 */
-               raw_spin_lock_irqsave(&ctx->lock, *flags);
+               raw_spin_lock(&ctx->lock);
                if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
-                       raw_spin_unlock_irqrestore(&ctx->lock, *flags);
+                       raw_spin_unlock(&ctx->lock);
                        rcu_read_unlock();
-                       preempt_enable();
+                       local_irq_restore(*flags);
                        goto retry;
                }
 
                if (!atomic_inc_not_zero(&ctx->refcount)) {
-                       raw_spin_unlock_irqrestore(&ctx->lock, *flags);
+                       raw_spin_unlock(&ctx->lock);
                        ctx = NULL;
                }
        }
        rcu_read_unlock();
-       preempt_enable();
+       if (!ctx)
+               local_irq_restore(*flags);
        return ctx;
 }
 
@@ -6913,6 +6914,10 @@ static int perf_tp_filter_match(struct perf_event *event,
 {
        void *record = data->raw->data;
 
+       /* only top level events have filters set */
+       if (event->parent)
+               event = event->parent;
+
        if (likely(!event->filter) || filter_match_preds(event->filter, record))
                return 1;
        return 0;
index 05c2188271b86730323c9bce053adc2d16e8d5a3..fcab63c669059308d3cc27054742587b0627b23f 100644 (file)
@@ -199,6 +199,11 @@ static inline int irq_desc_get_node(struct irq_desc *desc)
        return irq_common_data_get_node(&desc->irq_common_data);
 }
 
+static inline int irq_desc_is_chained(struct irq_desc *desc)
+{
+       return (desc->action && desc->action == &chained_action);
+}
+
 #ifdef CONFIG_PM_SLEEP
 bool irq_pm_check_wakeup(struct irq_desc *desc);
 void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action);
index e80c4400118ae7a8e3f09476964260490fccf01a..cea1de0161f18a164aebb84e275ad67d5899eda8 100644 (file)
@@ -70,7 +70,8 @@ void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
 
 static bool suspend_device_irq(struct irq_desc *desc)
 {
-       if (!desc->action || desc->no_suspend_depth)
+       if (!desc->action || irq_desc_is_chained(desc) ||
+           desc->no_suspend_depth)
                return false;
 
        if (irqd_is_wakeup_set(&desc->irq_data)) {
index a916cf144b6550caf452fc304a1e848d40246b8a..a2c02fd5d6d0f8c1ade72ab2680287f37321aa25 100644 (file)
@@ -475,7 +475,7 @@ int show_interrupts(struct seq_file *p, void *v)
        for_each_online_cpu(j)
                any_count |= kstat_irqs_cpu(i, j);
        action = desc->action;
-       if ((!action || action == &chained_action) && !any_count)
+       if ((!action || irq_desc_is_chained(desc)) && !any_count)
                goto out;
 
        seq_printf(p, "%*d: ", prec, i);
index 6e5344112419ca43ace3474466db35d1692752ab..db545cbcdb8933e1ab4b95a9c276eb523de8ba43 100644 (file)
@@ -294,6 +294,12 @@ static int klp_write_object_relocations(struct module *pmod,
 
        for (reloc = obj->relocs; reloc->name; reloc++) {
                if (!klp_is_module(obj)) {
+
+#if defined(CONFIG_RANDOMIZE_BASE)
+                       /* If KASLR has been enabled, adjust old value accordingly */
+                       if (kaslr_enabled())
+                               reloc->val += kaslr_offset();
+#endif
                        ret = klp_verify_vmlinux_symbol(reloc->name,
                                                        reloc->val);
                        if (ret)
index 4579dbb7ed872a7e1c119fdbbf98d9dc8cd67a87..4b150bc0c6c111ee09f783eaa6aa101339f6ceec 100644 (file)
@@ -152,8 +152,11 @@ void panic(const char *fmt, ...)
         * We may have ended up stopping the CPU holding the lock (in
         * smp_send_stop()) while still having some valuable data in the console
         * buffer.  Try to acquire the lock then release it regardless of the
-        * result.  The release will also print the buffers out.
+        * result.  The release will also print the buffers out.  Locks debug
+        * should be disabled to avoid reporting bad unlock balance when
+        * panic() is not being callled from OOPS.
         */
+       debug_locks_off();
        console_trylock();
        console_unlock();
 
index ca368793808e37688f7b0219b54d458fede30765..78b3d9f80d443fb4fa601e41088eb2041385ab20 100644 (file)
@@ -467,7 +467,7 @@ struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
        rcu_read_lock();
        if (type != PIDTYPE_PID)
                task = task->group_leader;
-       pid = get_pid(task->pids[type].pid);
+       pid = get_pid(rcu_dereference(task->pids[type].pid));
        rcu_read_unlock();
        return pid;
 }
@@ -528,7 +528,7 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
        if (likely(pid_alive(task))) {
                if (type != PIDTYPE_PID)
                        task = task->group_leader;
-               nr = pid_nr_ns(task->pids[type].pid, ns);
+               nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns);
        }
        rcu_read_unlock();
 
index 824aa9f501a3b2a183a5a700dee57c984c51f89e..f04fda8f669c8eff57e936fcb1334b13a4140ce5 100644 (file)
@@ -2302,7 +2302,7 @@ void task_tick_numa(struct rq *rq, struct task_struct *curr)
        now = curr->se.sum_exec_runtime;
        period = (u64)curr->numa_scan_period * NSEC_PER_MSEC;
 
-       if (now - curr->node_stamp > period) {
+       if (now > curr->node_stamp + period) {
                if (!curr->node_stamp)
                        curr->numa_scan_period = task_scan_min(curr);
                curr->node_stamp += period;
index c0b01fe24bbd3fae555b2e479e86f9199f3a7c3b..f3f1f7a972fd40f3d437d6bf3b5db2cacaffe6ca 100644 (file)
@@ -3503,7 +3503,7 @@ SYSCALL_DEFINE0(pause)
 
 #endif
 
-int sigsuspend(sigset_t *set)
+static int sigsuspend(sigset_t *set)
 {
        current->saved_sigmask = current->blocked;
        set_current_blocked(set);
index 74591ba9474f4dff4e0c3d7b7acedbe14b5d57a8..bbc5d1114583b21f1ab489cd40a98f3aa5ebd61d 100644 (file)
@@ -977,13 +977,29 @@ EXPORT_SYMBOL(add_timer);
  */
 void add_timer_on(struct timer_list *timer, int cpu)
 {
-       struct tvec_base *base = per_cpu_ptr(&tvec_bases, cpu);
+       struct tvec_base *new_base = per_cpu_ptr(&tvec_bases, cpu);
+       struct tvec_base *base;
        unsigned long flags;
 
        timer_stats_timer_set_start_info(timer);
        BUG_ON(timer_pending(timer) || !timer->function);
-       spin_lock_irqsave(&base->lock, flags);
-       timer->flags = (timer->flags & ~TIMER_BASEMASK) | cpu;
+
+       /*
+        * If @timer was on a different CPU, it should be migrated with the
+        * old base locked to prevent other operations proceeding with the
+        * wrong base locked.  See lock_timer_base().
+        */
+       base = lock_timer_base(timer, &flags);
+       if (base != new_base) {
+               timer->flags |= TIMER_MIGRATING;
+
+               spin_unlock(&base->lock);
+               base = new_base;
+               spin_lock(&base->lock);
+               WRITE_ONCE(timer->flags,
+                          (timer->flags & ~TIMER_BASEMASK) | cpu);
+       }
+
        debug_activate(timer, timer->expires);
        internal_add_timer(base, timer);
        spin_unlock_irqrestore(&base->lock, flags);
index 2198a630ef5826a30e51a2974d472b078273f80c..87fb9801bd9eead0d6e45bef49bc1eefc324c6a7 100644 (file)
@@ -100,8 +100,6 @@ static DEFINE_PER_CPU(bool, trace_cmdline_save);
  */
 static int tracing_disabled = 1;
 
-DEFINE_PER_CPU(int, ftrace_cpu_disabled);
-
 cpumask_var_t __read_mostly    tracing_buffer_mask;
 
 /*
@@ -1775,10 +1773,6 @@ trace_function(struct trace_array *tr,
        struct ring_buffer_event *event;
        struct ftrace_entry *entry;
 
-       /* If we are reading the ring buffer, don't trace */
-       if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
-               return;
-
        event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry),
                                          flags, pc);
        if (!event)
@@ -4554,6 +4548,8 @@ tracing_thresh_write(struct file *filp, const char __user *ubuf,
        return ret;
 }
 
+#ifdef CONFIG_TRACER_MAX_TRACE
+
 static ssize_t
 tracing_max_lat_read(struct file *filp, char __user *ubuf,
                     size_t cnt, loff_t *ppos)
@@ -4568,6 +4564,8 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
        return tracing_nsecs_write(filp->private_data, ubuf, cnt, ppos);
 }
 
+#endif
+
 static int tracing_open_pipe(struct inode *inode, struct file *filp)
 {
        struct trace_array *tr = inode->i_private;
@@ -5469,12 +5467,14 @@ static const struct file_operations tracing_thresh_fops = {
        .llseek         = generic_file_llseek,
 };
 
+#ifdef CONFIG_TRACER_MAX_TRACE
 static const struct file_operations tracing_max_lat_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_max_lat_read,
        .write          = tracing_max_lat_write,
        .llseek         = generic_file_llseek,
 };
+#endif
 
 static const struct file_operations set_tracer_fops = {
        .open           = tracing_open_generic,
@@ -6847,7 +6847,9 @@ struct dentry *tracing_init_dentry(void)
        if (tr->dir)
                return NULL;
 
-       if (WARN_ON(!debugfs_initialized()))
+       if (WARN_ON(!tracefs_initialized()) ||
+               (IS_ENABLED(CONFIG_DEBUG_FS) &&
+                WARN_ON(!debugfs_initialized())))
                return ERR_PTR(-ENODEV);
 
        /*
index dd7620802e725e1e2f262f77ba7d8c76dda98ef9..919d9d07686f5bcaad65699f400748a4b4db8a5e 100644 (file)
@@ -667,7 +667,6 @@ extern int DYN_FTRACE_TEST_NAME2(void);
 
 extern bool ring_buffer_expanded;
 extern bool tracing_selftest_disabled;
-DECLARE_PER_CPU(int, ftrace_cpu_disabled);
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
 extern int trace_selftest_startup_function(struct tracer *trace,
index 92382af7a21312c03ecef0cabdfbce19e2c8111e..a663cbb84107d71039200011e4b3ec5f897c9213 100644 (file)
@@ -288,9 +288,6 @@ int __trace_graph_entry(struct trace_array *tr,
        struct ring_buffer *buffer = tr->trace_buffer.buffer;
        struct ftrace_graph_ent_entry *entry;
 
-       if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
-               return 0;
-
        event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT,
                                          sizeof(*entry), flags, pc);
        if (!event)
@@ -403,9 +400,6 @@ void __trace_graph_return(struct trace_array *tr,
        struct ring_buffer *buffer = tr->trace_buffer.buffer;
        struct ftrace_graph_ret_entry *entry;
 
-       if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
-               return;
-
        event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET,
                                          sizeof(*entry), flags, pc);
        if (!event)
index c29ddebc870509e7e35b69da5cce5a7d9988542d..62fe06bb7d04bacccc8c2213a6a65134fa274010 100644 (file)
@@ -2009,7 +2009,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_HUGEPAGE | VM_NO_THP))
+               if (*vm_flags & VM_NO_THP)
                        return -EINVAL;
                *vm_flags &= ~VM_NOHUGEPAGE;
                *vm_flags |= VM_HUGEPAGE;
@@ -2025,7 +2025,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_NOHUGEPAGE | VM_NO_THP))
+               if (*vm_flags & VM_NO_THP)
                        return -EINVAL;
                *vm_flags &= ~VM_HUGEPAGE;
                *vm_flags |= VM_NOHUGEPAGE;
index d41b21bce6a030a0ea0356d34e9a495f6dfbb5b0..bc0a8d8b8f42faf7bca01501425ba73e156ee293 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kmemleak.h>
 #include <linux/memblock.h>
 #include <linux/memory.h>
 #include <linux/mm.h>
@@ -444,6 +445,7 @@ int kasan_module_alloc(void *addr, size_t size)
 
        if (ret) {
                find_vm_area(addr)->flags |= VM_KASAN;
+               kmemleak_ignore(ret);
                return 0;
        }
 
index deb679c31f2ab897cafebf72643aec4f66233308..c387430f06c319d52794152b7e100a66a10c9f68 100644 (file)
@@ -3015,9 +3015,9 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                } else {
                        /*
                         * The fault handler has no page to lock, so it holds
-                        * i_mmap_lock for write to protect against truncate.
+                        * i_mmap_lock for read to protect against truncate.
                         */
-                       i_mmap_unlock_write(vma->vm_file->f_mapping);
+                       i_mmap_unlock_read(vma->vm_file->f_mapping);
                }
                goto uncharge_out;
        }
@@ -3031,9 +3031,9 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        } else {
                /*
                 * The fault handler has no page to lock, so it holds
-                * i_mmap_lock for write to protect against truncate.
+                * i_mmap_lock for read to protect against truncate.
                 */
-               i_mmap_unlock_write(vma->vm_file->f_mapping);
+               i_mmap_unlock_read(vma->vm_file->f_mapping);
        }
        return ret;
 uncharge_out:
index 2c90357c34ea4c4d81521b7bf14d669d6565cc07..3e4d65445fa71d7d629868c1db70af2bfb1fab28 100644 (file)
@@ -1542,7 +1542,9 @@ static void balance_dirty_pages(struct address_space *mapping,
        for (;;) {
                unsigned long now = jiffies;
                unsigned long dirty, thresh, bg_thresh;
-               unsigned long m_dirty, m_thresh, m_bg_thresh;
+               unsigned long m_dirty = 0;      /* stop bogus uninit warnings */
+               unsigned long m_thresh = 0;
+               unsigned long m_bg_thresh = 0;
 
                /*
                 * Unstable writes are a feature of certain networked
index e0819fa96559f3d166a35001dbefd4982ffd2a08..4765c97ce6900d98b8ce2968cf9ff62a176f6e42 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3419,7 +3419,7 @@ void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
 }
 EXPORT_SYMBOL(kmem_cache_free_bulk);
 
-bool kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
+int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
                                                                void **p)
 {
        return __kmem_cache_alloc_bulk(s, flags, size, p);
index 27492eb678f722400147e22da62a68de893497e8..7b608719799763cb075c35e3fd4c15e0fddc18b5 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -170,7 +170,7 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
  * may be allocated or freed using these operations.
  */
 void __kmem_cache_free_bulk(struct kmem_cache *, size_t, void **);
-bool __kmem_cache_alloc_bulk(struct kmem_cache *, gfp_t, size_t, void **);
+int __kmem_cache_alloc_bulk(struct kmem_cache *, gfp_t, size_t, void **);
 
 #ifdef CONFIG_MEMCG_KMEM
 /*
index d88e97c10a2e31669753681efc74f6bf50fdf2ef..3c6a86b4ec25f8462c1584dcb5bcf01e4edbd4ff 100644 (file)
@@ -112,7 +112,7 @@ void __kmem_cache_free_bulk(struct kmem_cache *s, size_t nr, void **p)
                kmem_cache_free(s, p[i]);
 }
 
-bool __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
+int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
                                                                void **p)
 {
        size_t i;
@@ -121,10 +121,10 @@ bool __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
                void *x = p[i] = kmem_cache_alloc(s, flags);
                if (!x) {
                        __kmem_cache_free_bulk(s, i, p);
-                       return false;
+                       return 0;
                }
        }
-       return true;
+       return i;
 }
 
 #ifdef CONFIG_MEMCG_KMEM
index 0d7e5df74d1f03e7069d1d938452b9474bc9a969..17e8f8cc7c534adca165f6d0e9b546e2f8484148 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -617,7 +617,7 @@ void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
 }
 EXPORT_SYMBOL(kmem_cache_free_bulk);
 
-bool kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
+int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
                                                                void **p)
 {
        return __kmem_cache_alloc_bulk(s, flags, size, p);
index 7cb4bf9ae32002494e519130a71af0532de4af87..46997517406ede0e987388763c9fa1d07875c1db 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1065,11 +1065,15 @@ static noinline int alloc_debug_processing(struct kmem_cache *s,
        return 0;
 }
 
+/* Supports checking bulk free of a constructed freelist */
 static noinline struct kmem_cache_node *free_debug_processing(
-       struct kmem_cache *s, struct page *page, void *object,
+       struct kmem_cache *s, struct page *page,
+       void *head, void *tail, int bulk_cnt,
        unsigned long addr, unsigned long *flags)
 {
        struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+       void *object = head;
+       int cnt = 0;
 
        spin_lock_irqsave(&n->list_lock, *flags);
        slab_lock(page);
@@ -1077,6 +1081,9 @@ static noinline struct kmem_cache_node *free_debug_processing(
        if (!check_slab(s, page))
                goto fail;
 
+next_object:
+       cnt++;
+
        if (!check_valid_pointer(s, page, object)) {
                slab_err(s, page, "Invalid object pointer 0x%p", object);
                goto fail;
@@ -1107,8 +1114,19 @@ static noinline struct kmem_cache_node *free_debug_processing(
        if (s->flags & SLAB_STORE_USER)
                set_track(s, object, TRACK_FREE, addr);
        trace(s, page, object, 0);
+       /* Freepointer not overwritten by init_object(), SLAB_POISON moved it */
        init_object(s, object, SLUB_RED_INACTIVE);
+
+       /* Reached end of constructed freelist yet? */
+       if (object != tail) {
+               object = get_freepointer(s, object);
+               goto next_object;
+       }
 out:
+       if (cnt != bulk_cnt)
+               slab_err(s, page, "Bulk freelist count(%d) invalid(%d)\n",
+                        bulk_cnt, cnt);
+
        slab_unlock(page);
        /*
         * Keep node_lock to preserve integrity
@@ -1204,7 +1222,7 @@ unsigned long kmem_cache_flags(unsigned long object_size,
 
        return flags;
 }
-#else
+#else /* !CONFIG_SLUB_DEBUG */
 static inline void setup_object_debug(struct kmem_cache *s,
                        struct page *page, void *object) {}
 
@@ -1212,7 +1230,8 @@ static inline int alloc_debug_processing(struct kmem_cache *s,
        struct page *page, void *object, unsigned long addr) { return 0; }
 
 static inline struct kmem_cache_node *free_debug_processing(
-       struct kmem_cache *s, struct page *page, void *object,
+       struct kmem_cache *s, struct page *page,
+       void *head, void *tail, int bulk_cnt,
        unsigned long addr, unsigned long *flags) { return NULL; }
 
 static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
@@ -1273,14 +1292,21 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
        return memcg_kmem_get_cache(s, flags);
 }
 
-static inline void slab_post_alloc_hook(struct kmem_cache *s,
-                                       gfp_t flags, void *object)
+static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
+                                       size_t size, void **p)
 {
+       size_t i;
+
        flags &= gfp_allowed_mask;
-       kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
-       kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags);
+       for (i = 0; i < size; i++) {
+               void *object = p[i];
+
+               kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
+               kmemleak_alloc_recursive(object, s->object_size, 1,
+                                        s->flags, flags);
+               kasan_slab_alloc(s, object);
+       }
        memcg_kmem_put_cache(s);
-       kasan_slab_alloc(s, object);
 }
 
 static inline void slab_free_hook(struct kmem_cache *s, void *x)
@@ -1308,6 +1334,29 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x)
        kasan_slab_free(s, x);
 }
 
+static inline void slab_free_freelist_hook(struct kmem_cache *s,
+                                          void *head, void *tail)
+{
+/*
+ * Compiler cannot detect this function can be removed if slab_free_hook()
+ * evaluates to nothing.  Thus, catch all relevant config debug options here.
+ */
+#if defined(CONFIG_KMEMCHECK) ||               \
+       defined(CONFIG_LOCKDEP) ||              \
+       defined(CONFIG_DEBUG_KMEMLEAK) ||       \
+       defined(CONFIG_DEBUG_OBJECTS_FREE) ||   \
+       defined(CONFIG_KASAN)
+
+       void *object = head;
+       void *tail_obj = tail ? : head;
+
+       do {
+               slab_free_hook(s, object);
+       } while ((object != tail_obj) &&
+                (object = get_freepointer(s, object)));
+#endif
+}
+
 static void setup_object(struct kmem_cache *s, struct page *page,
                                void *object)
 {
@@ -2295,23 +2344,15 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
  * And if we were unable to get a new slab from the partial slab lists then
  * we need to allocate a new slab. This is the slowest path since it involves
  * a call to the page allocator and the setup of a new slab.
+ *
+ * Version of __slab_alloc to use when we know that interrupts are
+ * already disabled (which is the case for bulk allocation).
  */
-static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
+static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
                          unsigned long addr, struct kmem_cache_cpu *c)
 {
        void *freelist;
        struct page *page;
-       unsigned long flags;
-
-       local_irq_save(flags);
-#ifdef CONFIG_PREEMPT
-       /*
-        * We may have been preempted and rescheduled on a different
-        * cpu before disabling interrupts. Need to reload cpu area
-        * pointer.
-        */
-       c = this_cpu_ptr(s->cpu_slab);
-#endif
 
        page = c->page;
        if (!page)
@@ -2369,7 +2410,6 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
        VM_BUG_ON(!c->page->frozen);
        c->freelist = get_freepointer(s, freelist);
        c->tid = next_tid(c->tid);
-       local_irq_restore(flags);
        return freelist;
 
 new_slab:
@@ -2386,7 +2426,6 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 
        if (unlikely(!freelist)) {
                slab_out_of_memory(s, gfpflags, node);
-               local_irq_restore(flags);
                return NULL;
        }
 
@@ -2402,10 +2441,34 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
        deactivate_slab(s, page, get_freepointer(s, freelist));
        c->page = NULL;
        c->freelist = NULL;
-       local_irq_restore(flags);
        return freelist;
 }
 
+/*
+ * Another one that disabled interrupt and compensates for possible
+ * cpu changes by refetching the per cpu area pointer.
+ */
+static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
+                         unsigned long addr, struct kmem_cache_cpu *c)
+{
+       void *p;
+       unsigned long flags;
+
+       local_irq_save(flags);
+#ifdef CONFIG_PREEMPT
+       /*
+        * We may have been preempted and rescheduled on a different
+        * cpu before disabling interrupts. Need to reload cpu area
+        * pointer.
+        */
+       c = this_cpu_ptr(s->cpu_slab);
+#endif
+
+       p = ___slab_alloc(s, gfpflags, node, addr, c);
+       local_irq_restore(flags);
+       return p;
+}
+
 /*
  * Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc)
  * have the fastpath folded into their functions. So no function call
@@ -2419,7 +2482,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 static __always_inline void *slab_alloc_node(struct kmem_cache *s,
                gfp_t gfpflags, int node, unsigned long addr)
 {
-       void **object;
+       void *object;
        struct kmem_cache_cpu *c;
        struct page *page;
        unsigned long tid;
@@ -2498,7 +2561,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
        if (unlikely(gfpflags & __GFP_ZERO) && object)
                memset(object, 0, s->object_size);
 
-       slab_post_alloc_hook(s, gfpflags, object);
+       slab_post_alloc_hook(s, gfpflags, 1, &object);
 
        return object;
 }
@@ -2569,10 +2632,11 @@ EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
  * handling required then we can return immediately.
  */
 static void __slab_free(struct kmem_cache *s, struct page *page,
-                       void *x, unsigned long addr)
+                       void *head, void *tail, int cnt,
+                       unsigned long addr)
+
 {
        void *prior;
-       void **object = (void *)x;
        int was_frozen;
        struct page new;
        unsigned long counters;
@@ -2582,7 +2646,8 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
        stat(s, FREE_SLOWPATH);
 
        if (kmem_cache_debug(s) &&
-               !(n = free_debug_processing(s, page, x, addr, &flags)))
+           !(n = free_debug_processing(s, page, head, tail, cnt,
+                                       addr, &flags)))
                return;
 
        do {
@@ -2592,10 +2657,10 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
                }
                prior = page->freelist;
                counters = page->counters;
-               set_freepointer(s, object, prior);
+               set_freepointer(s, tail, prior);
                new.counters = counters;
                was_frozen = new.frozen;
-               new.inuse--;
+               new.inuse -= cnt;
                if ((!new.inuse || !prior) && !was_frozen) {
 
                        if (kmem_cache_has_cpu_partial(s) && !prior) {
@@ -2626,7 +2691,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 
        } while (!cmpxchg_double_slab(s, page,
                prior, counters,
-               object, new.counters,
+               head, new.counters,
                "__slab_free"));
 
        if (likely(!n)) {
@@ -2691,15 +2756,20 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
  *
  * If fastpath is not possible then fall back to __slab_free where we deal
  * with all sorts of special processing.
+ *
+ * Bulk free of a freelist with several objects (all pointing to the
+ * same page) possible by specifying head and tail ptr, plus objects
+ * count (cnt). Bulk free indicated by tail pointer being set.
  */
-static __always_inline void slab_free(struct kmem_cache *s,
-                       struct page *page, void *x, unsigned long addr)
+static __always_inline void slab_free(struct kmem_cache *s, struct page *page,
+                                     void *head, void *tail, int cnt,
+                                     unsigned long addr)
 {
-       void **object = (void *)x;
+       void *tail_obj = tail ? : head;
        struct kmem_cache_cpu *c;
        unsigned long tid;
 
-       slab_free_hook(s, x);
+       slab_free_freelist_hook(s, head, tail);
 
 redo:
        /*
@@ -2718,19 +2788,19 @@ static __always_inline void slab_free(struct kmem_cache *s,
        barrier();
 
        if (likely(page == c->page)) {
-               set_freepointer(s, object, c->freelist);
+               set_freepointer(s, tail_obj, c->freelist);
 
                if (unlikely(!this_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                c->freelist, tid,
-                               object, next_tid(tid)))) {
+                               head, next_tid(tid)))) {
 
                        note_cmpxchg_failure("slab_free", s, tid);
                        goto redo;
                }
                stat(s, FREE_FASTPATH);
        } else
-               __slab_free(s, page, x, addr);
+               __slab_free(s, page, head, tail_obj, cnt, addr);
 
 }
 
@@ -2739,59 +2809,116 @@ void kmem_cache_free(struct kmem_cache *s, void *x)
        s = cache_from_obj(s, x);
        if (!s)
                return;
-       slab_free(s, virt_to_head_page(x), x, _RET_IP_);
+       slab_free(s, virt_to_head_page(x), x, NULL, 1, _RET_IP_);
        trace_kmem_cache_free(_RET_IP_, x);
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
-/* Note that interrupts must be enabled when calling this function. */
-void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
-{
-       struct kmem_cache_cpu *c;
+struct detached_freelist {
        struct page *page;
-       int i;
+       void *tail;
+       void *freelist;
+       int cnt;
+};
 
-       local_irq_disable();
-       c = this_cpu_ptr(s->cpu_slab);
+/*
+ * This function progressively scans the array with free objects (with
+ * a limited look ahead) and extract objects belonging to the same
+ * page.  It builds a detached freelist directly within the given
+ * page/objects.  This can happen without any need for
+ * synchronization, because the objects are owned by running process.
+ * The freelist is build up as a single linked list in the objects.
+ * The idea is, that this detached freelist can then be bulk
+ * transferred to the real freelist(s), but only requiring a single
+ * synchronization primitive.  Look ahead in the array is limited due
+ * to performance reasons.
+ */
+static int build_detached_freelist(struct kmem_cache *s, size_t size,
+                                  void **p, struct detached_freelist *df)
+{
+       size_t first_skipped_index = 0;
+       int lookahead = 3;
+       void *object;
 
-       for (i = 0; i < size; i++) {
-               void *object = p[i];
+       /* Always re-init detached_freelist */
+       df->page = NULL;
 
-               BUG_ON(!object);
-               /* kmem cache debug support */
-               s = cache_from_obj(s, object);
-               if (unlikely(!s))
-                       goto exit;
-               slab_free_hook(s, object);
+       do {
+               object = p[--size];
+       } while (!object && size);
 
-               page = virt_to_head_page(object);
+       if (!object)
+               return 0;
 
-               if (c->page == page) {
-                       /* Fastpath: local CPU free */
-                       set_freepointer(s, object, c->freelist);
-                       c->freelist = object;
-               } else {
-                       c->tid = next_tid(c->tid);
-                       local_irq_enable();
-                       /* Slowpath: overhead locked cmpxchg_double_slab */
-                       __slab_free(s, page, object, _RET_IP_);
-                       local_irq_disable();
-                       c = this_cpu_ptr(s->cpu_slab);
+       /* Start new detached freelist */
+       set_freepointer(s, object, NULL);
+       df->page = virt_to_head_page(object);
+       df->tail = object;
+       df->freelist = object;
+       p[size] = NULL; /* mark object processed */
+       df->cnt = 1;
+
+       while (size) {
+               object = p[--size];
+               if (!object)
+                       continue; /* Skip processed objects */
+
+               /* df->page is always set at this point */
+               if (df->page == virt_to_head_page(object)) {
+                       /* Opportunity build freelist */
+                       set_freepointer(s, object, df->freelist);
+                       df->freelist = object;
+                       df->cnt++;
+                       p[size] = NULL; /* mark object processed */
+
+                       continue;
                }
+
+               /* Limit look ahead search */
+               if (!--lookahead)
+                       break;
+
+               if (!first_skipped_index)
+                       first_skipped_index = size + 1;
        }
-exit:
-       c->tid = next_tid(c->tid);
-       local_irq_enable();
+
+       return first_skipped_index;
+}
+
+
+/* Note that interrupts must be enabled when calling this function. */
+void kmem_cache_free_bulk(struct kmem_cache *orig_s, size_t size, void **p)
+{
+       if (WARN_ON(!size))
+               return;
+
+       do {
+               struct detached_freelist df;
+               struct kmem_cache *s;
+
+               /* Support for memcg */
+               s = cache_from_obj(orig_s, p[size - 1]);
+
+               size = build_detached_freelist(s, size, p, &df);
+               if (unlikely(!df.page))
+                       continue;
+
+               slab_free(s, df.page, df.freelist, df.tail, df.cnt, _RET_IP_);
+       } while (likely(size));
 }
 EXPORT_SYMBOL(kmem_cache_free_bulk);
 
 /* Note that interrupts must be enabled when calling this function. */
-bool kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
-                          void **p)
+int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
+                         void **p)
 {
        struct kmem_cache_cpu *c;
        int i;
 
+       /* memcg and kmem_cache debug support */
+       s = slab_pre_alloc_hook(s, flags);
+       if (unlikely(!s))
+               return false;
        /*
         * Drain objects in the per cpu slab, while disabling local
         * IRQs, which protects against PREEMPT and interrupts
@@ -2804,36 +2931,20 @@ bool kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
                void *object = c->freelist;
 
                if (unlikely(!object)) {
-                       local_irq_enable();
                        /*
                         * Invoking slow path likely have side-effect
                         * of re-populating per CPU c->freelist
                         */
-                       p[i] = __slab_alloc(s, flags, NUMA_NO_NODE,
+                       p[i] = ___slab_alloc(s, flags, NUMA_NO_NODE,
                                            _RET_IP_, c);
-                       if (unlikely(!p[i])) {
-                               __kmem_cache_free_bulk(s, i, p);
-                               return false;
-                       }
-                       local_irq_disable();
+                       if (unlikely(!p[i]))
+                               goto error;
+
                        c = this_cpu_ptr(s->cpu_slab);
                        continue; /* goto for-loop */
                }
-
-               /* kmem_cache debug support */
-               s = slab_pre_alloc_hook(s, flags);
-               if (unlikely(!s)) {
-                       __kmem_cache_free_bulk(s, i, p);
-                       c->tid = next_tid(c->tid);
-                       local_irq_enable();
-                       return false;
-               }
-
                c->freelist = get_freepointer(s, object);
                p[i] = object;
-
-               /* kmem_cache debug support */
-               slab_post_alloc_hook(s, flags, object);
        }
        c->tid = next_tid(c->tid);
        local_irq_enable();
@@ -2846,7 +2957,14 @@ bool kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
                        memset(p[j], 0, s->object_size);
        }
 
-       return true;
+       /* memcg and kmem_cache debug support */
+       slab_post_alloc_hook(s, flags, size, p);
+       return i;
+error:
+       local_irq_enable();
+       slab_post_alloc_hook(s, flags, i, p);
+       __kmem_cache_free_bulk(s, i, p);
+       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_bulk);
 
@@ -3511,7 +3629,7 @@ void kfree(const void *x)
                __free_kmem_pages(page, compound_order(page));
                return;
        }
-       slab_free(page->slab_cache, page, object, _RET_IP_);
+       slab_free(page->slab_cache, page, object, NULL, 1, _RET_IP_);
 }
 EXPORT_SYMBOL(kfree);
 
index d04563480c94f4137efb6102e8d8beaef3a9dda7..8e3c9c5a3042b6149ff783bb1dfc0c0e08dc4046 100644 (file)
@@ -1443,7 +1443,6 @@ struct vm_struct *remove_vm_area(const void *addr)
                vmap_debug_free_range(va->va_start, va->va_end);
                kasan_free_shadow(vm);
                free_unmap_vmap_area(va);
-               vm->size -= PAGE_SIZE;
 
                return vm;
        }
@@ -1468,8 +1467,8 @@ static void __vunmap(const void *addr, int deallocate_pages)
                return;
        }
 
-       debug_check_no_locks_freed(addr, area->size);
-       debug_check_no_obj_freed(addr, area->size);
+       debug_check_no_locks_freed(addr, get_vm_area_size(area));
+       debug_check_no_obj_freed(addr, get_vm_area_size(area));
 
        if (deallocate_pages) {
                int i;
index 496b27588493ded6edb0bf408440ecaa56dcd59c..e2ed69850489bb79a6a055ee3264456a31acee3e 100644 (file)
@@ -30,7 +30,9 @@ bool vlan_do_receive(struct sk_buff **skbp)
                        skb->pkt_type = PACKET_HOST;
        }
 
-       if (!(vlan_dev_priv(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR)) {
+       if (!(vlan_dev_priv(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR) &&
+           !netif_is_macvlan_port(vlan_dev) &&
+           !netif_is_bridge_port(vlan_dev)) {
                unsigned int offset = skb->data - skb_mac_header(skb);
 
                /*
index f7e8dee64fc80ec04152788c945dea1b346b3dcd..5f3f6455317924e0e74281d23075d2af68d72d73 100644 (file)
@@ -48,7 +48,7 @@ void br_set_state(struct net_bridge_port *p, unsigned int state)
 
        p->state = state;
        err = switchdev_port_attr_set(p->dev, &attr);
-       if (err)
+       if (err && err != -EOPNOTSUPP)
                br_warn(p->br, "error setting offload STP state on port %u(%s)\n",
                                (unsigned int) p->port_no, p->dev->name);
 }
index fa53d7a89f485ac9039b6168db3063512c4d9d42..5396ff08af3215d1a532b853c8859fb64dfc6a1f 100644 (file)
@@ -50,7 +50,7 @@ void br_init_port(struct net_bridge_port *p)
        p->config_pending = 0;
 
        err = switchdev_port_attr_set(p->dev, &attr);
-       if (err)
+       if (err && err != -EOPNOTSUPP)
                netdev_err(p->dev, "failed to set HW ageing time\n");
 }
 
index ba6eb17226da424d59bb462a2089186bbd3233af..10d87753ed8737329c244b1ae7718e95c8abd118 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/ceph/decode.h>
 #include <linux/ceph/auth.h>
+#include <linux/ceph/libceph.h>
 #include <linux/ceph/messenger.h>
 
 #include "crypto.h"
@@ -279,6 +280,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
        return -EINVAL;
 }
 
+static void ceph_x_authorizer_cleanup(struct ceph_x_authorizer *au)
+{
+       ceph_crypto_key_destroy(&au->session_key);
+       if (au->buf) {
+               ceph_buffer_put(au->buf);
+               au->buf = NULL;
+       }
+}
+
 static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
                                   struct ceph_x_ticket_handler *th,
                                   struct ceph_x_authorizer *au)
@@ -297,7 +307,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        ceph_crypto_key_destroy(&au->session_key);
        ret = ceph_crypto_key_clone(&au->session_key, &th->session_key);
        if (ret)
-               return ret;
+               goto out_au;
 
        maxlen = sizeof(*msg_a) + sizeof(msg_b) +
                ceph_x_encrypt_buflen(ticket_blob_len);
@@ -309,8 +319,8 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        if (!au->buf) {
                au->buf = ceph_buffer_new(maxlen, GFP_NOFS);
                if (!au->buf) {
-                       ceph_crypto_key_destroy(&au->session_key);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto out_au;
                }
        }
        au->service = th->service;
@@ -340,7 +350,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        ret = ceph_x_encrypt(&au->session_key, &msg_b, sizeof(msg_b),
                             p, end - p);
        if (ret < 0)
-               goto out_buf;
+               goto out_au;
        p += ret;
        au->buf->vec.iov_len = p - au->buf->vec.iov_base;
        dout(" built authorizer nonce %llx len %d\n", au->nonce,
@@ -348,9 +358,8 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        BUG_ON(au->buf->vec.iov_len > maxlen);
        return 0;
 
-out_buf:
-       ceph_buffer_put(au->buf);
-       au->buf = NULL;
+out_au:
+       ceph_x_authorizer_cleanup(au);
        return ret;
 }
 
@@ -624,8 +633,7 @@ static void ceph_x_destroy_authorizer(struct ceph_auth_client *ac,
 {
        struct ceph_x_authorizer *au = (void *)a;
 
-       ceph_crypto_key_destroy(&au->session_key);
-       ceph_buffer_put(au->buf);
+       ceph_x_authorizer_cleanup(au);
        kfree(au);
 }
 
@@ -653,8 +661,7 @@ static void ceph_x_destroy(struct ceph_auth_client *ac)
                remove_ticket_handler(ac, th);
        }
 
-       if (xi->auth_authorizer.buf)
-               ceph_buffer_put(xi->auth_authorizer.buf);
+       ceph_x_authorizer_cleanup(&xi->auth_authorizer);
 
        kfree(ac->private);
        ac->private = NULL;
@@ -691,8 +698,10 @@ static int ceph_x_sign_message(struct ceph_auth_handshake *auth,
                               struct ceph_msg *msg)
 {
        int ret;
-       if (!auth->authorizer)
+
+       if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
                return 0;
+
        ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
                              msg, &msg->footer.sig);
        if (ret < 0)
@@ -707,8 +716,9 @@ static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth,
        __le64 sig_check;
        int ret;
 
-       if (!auth->authorizer)
+       if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN))
                return 0;
+
        ret = calcu_signature((struct ceph_x_authorizer *)auth->authorizer,
                              msg, &sig_check);
        if (ret < 0)
index 78f098a20796d7dd0d71b364c5de3d99239dc4ac..bcbec33c6a14a8f5d962fb1d803a6503a6e11f9b 100644 (file)
@@ -245,6 +245,8 @@ enum {
        Opt_nocrc,
        Opt_cephx_require_signatures,
        Opt_nocephx_require_signatures,
+       Opt_cephx_sign_messages,
+       Opt_nocephx_sign_messages,
        Opt_tcp_nodelay,
        Opt_notcp_nodelay,
 };
@@ -267,6 +269,8 @@ static match_table_t opt_tokens = {
        {Opt_nocrc, "nocrc"},
        {Opt_cephx_require_signatures, "cephx_require_signatures"},
        {Opt_nocephx_require_signatures, "nocephx_require_signatures"},
+       {Opt_cephx_sign_messages, "cephx_sign_messages"},
+       {Opt_nocephx_sign_messages, "nocephx_sign_messages"},
        {Opt_tcp_nodelay, "tcp_nodelay"},
        {Opt_notcp_nodelay, "notcp_nodelay"},
        {-1, NULL}
@@ -491,6 +495,12 @@ ceph_parse_options(char *options, const char *dev_name,
                case Opt_nocephx_require_signatures:
                        opt->flags |= CEPH_OPT_NOMSGAUTH;
                        break;
+               case Opt_cephx_sign_messages:
+                       opt->flags &= ~CEPH_OPT_NOMSGSIGN;
+                       break;
+               case Opt_nocephx_sign_messages:
+                       opt->flags |= CEPH_OPT_NOMSGSIGN;
+                       break;
 
                case Opt_tcp_nodelay:
                        opt->flags |= CEPH_OPT_TCP_NODELAY;
@@ -534,6 +544,8 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
                seq_puts(m, "nocrc,");
        if (opt->flags & CEPH_OPT_NOMSGAUTH)
                seq_puts(m, "nocephx_require_signatures,");
+       if (opt->flags & CEPH_OPT_NOMSGSIGN)
+               seq_puts(m, "nocephx_sign_messages,");
        if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
                seq_puts(m, "notcp_nodelay,");
 
@@ -596,11 +608,7 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private,
        if (ceph_test_opt(client, MYIP))
                myaddr = &client->options->my_addr;
 
-       ceph_messenger_init(&client->msgr, myaddr,
-               client->supported_features,
-               client->required_features,
-               ceph_test_opt(client, NOCRC),
-               ceph_test_opt(client, TCP_NODELAY));
+       ceph_messenger_init(&client->msgr, myaddr);
 
        /* subsystems */
        err = ceph_monc_init(&client->monc, client);
index d1498224c49d4c6c18e082ea908cb3e5a8fed30c..2e9cab09f37ba65c9c5961c12e10d2aded02413f 100644 (file)
@@ -16,8 +16,10 @@ struct ceph_crypto_key {
 
 static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
 {
-       if (key)
+       if (key) {
                kfree(key->key);
+               key->key = NULL;
+       }
 }
 
 int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
index b9b0e3b5da49f84d9fb1775e75aca83f55e80b2d..9981039ef4ffcca29081b83a5e06a81ce6871f20 100644 (file)
@@ -509,7 +509,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                return ret;
        }
 
-       if (con->msgr->tcp_nodelay) {
+       if (ceph_test_opt(from_msgr(con->msgr), TCP_NODELAY)) {
                int optval = 1;
 
                ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
@@ -637,9 +637,6 @@ static int con_close_socket(struct ceph_connection *con)
 static void ceph_msg_remove(struct ceph_msg *msg)
 {
        list_del_init(&msg->list_head);
-       BUG_ON(msg->con == NULL);
-       msg->con->ops->put(msg->con);
-       msg->con = NULL;
 
        ceph_msg_put(msg);
 }
@@ -662,15 +659,14 @@ static void reset_connection(struct ceph_connection *con)
 
        if (con->in_msg) {
                BUG_ON(con->in_msg->con != con);
-               con->in_msg->con = NULL;
                ceph_msg_put(con->in_msg);
                con->in_msg = NULL;
-               con->ops->put(con);
        }
 
        con->connect_seq = 0;
        con->out_seq = 0;
        if (con->out_msg) {
+               BUG_ON(con->out_msg->con != con);
                ceph_msg_put(con->out_msg);
                con->out_msg = NULL;
        }
@@ -1205,7 +1201,7 @@ static void prepare_write_message_footer(struct ceph_connection *con)
        con->out_kvec[v].iov_base = &m->footer;
        if (con->peer_features & CEPH_FEATURE_MSG_AUTH) {
                if (con->ops->sign_message)
-                       con->ops->sign_message(con, m);
+                       con->ops->sign_message(m);
                else
                        m->footer.sig = 0;
                con->out_kvec[v].iov_len = sizeof(m->footer);
@@ -1432,7 +1428,8 @@ static int prepare_write_connect(struct ceph_connection *con)
        dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
             con->connect_seq, global_seq, proto);
 
-       con->out_connect.features = cpu_to_le64(con->msgr->supported_features);
+       con->out_connect.features =
+           cpu_to_le64(from_msgr(con->msgr)->supported_features);
        con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
        con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
        con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -1527,7 +1524,7 @@ static int write_partial_message_data(struct ceph_connection *con)
 {
        struct ceph_msg *msg = con->out_msg;
        struct ceph_msg_data_cursor *cursor = &msg->cursor;
-       bool do_datacrc = !con->msgr->nocrc;
+       bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
        u32 crc;
 
        dout("%s %p msg %p\n", __func__, con, msg);
@@ -1552,8 +1549,8 @@ static int write_partial_message_data(struct ceph_connection *con)
                bool need_crc;
                int ret;
 
-               page = ceph_msg_data_next(&msg->cursor, &page_offset, &length,
-                                                       &last_piece);
+               page = ceph_msg_data_next(cursor, &page_offset, &length,
+                                         &last_piece);
                ret = ceph_tcp_sendpage(con->sock, page, page_offset,
                                        length, !last_piece);
                if (ret <= 0) {
@@ -1564,7 +1561,7 @@ static int write_partial_message_data(struct ceph_connection *con)
                }
                if (do_datacrc && cursor->need_crc)
                        crc = ceph_crc32c_page(crc, page, page_offset, length);
-               need_crc = ceph_msg_data_advance(&msg->cursor, (size_t)ret);
+               need_crc = ceph_msg_data_advance(cursor, (size_t)ret);
        }
 
        dout("%s %p msg %p done\n", __func__, con, msg);
@@ -2005,8 +2002,8 @@ static int process_banner(struct ceph_connection *con)
 
 static int process_connect(struct ceph_connection *con)
 {
-       u64 sup_feat = con->msgr->supported_features;
-       u64 req_feat = con->msgr->required_features;
+       u64 sup_feat = from_msgr(con->msgr)->supported_features;
+       u64 req_feat = from_msgr(con->msgr)->required_features;
        u64 server_feat = ceph_sanitize_features(
                                le64_to_cpu(con->in_reply.features));
        int ret;
@@ -2232,7 +2229,7 @@ static int read_partial_msg_data(struct ceph_connection *con)
 {
        struct ceph_msg *msg = con->in_msg;
        struct ceph_msg_data_cursor *cursor = &msg->cursor;
-       const bool do_datacrc = !con->msgr->nocrc;
+       bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
        struct page *page;
        size_t page_offset;
        size_t length;
@@ -2246,8 +2243,7 @@ static int read_partial_msg_data(struct ceph_connection *con)
        if (do_datacrc)
                crc = con->in_data_crc;
        while (cursor->resid) {
-               page = ceph_msg_data_next(&msg->cursor, &page_offset, &length,
-                                                       NULL);
+               page = ceph_msg_data_next(cursor, &page_offset, &length, NULL);
                ret = ceph_tcp_recvpage(con->sock, page, page_offset, length);
                if (ret <= 0) {
                        if (do_datacrc)
@@ -2258,7 +2254,7 @@ static int read_partial_msg_data(struct ceph_connection *con)
 
                if (do_datacrc)
                        crc = ceph_crc32c_page(crc, page, page_offset, ret);
-               (void) ceph_msg_data_advance(&msg->cursor, (size_t)ret);
+               (void) ceph_msg_data_advance(cursor, (size_t)ret);
        }
        if (do_datacrc)
                con->in_data_crc = crc;
@@ -2278,7 +2274,7 @@ static int read_partial_message(struct ceph_connection *con)
        int end;
        int ret;
        unsigned int front_len, middle_len, data_len;
-       bool do_datacrc = !con->msgr->nocrc;
+       bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
        bool need_sign = (con->peer_features & CEPH_FEATURE_MSG_AUTH);
        u64 seq;
        u32 crc;
@@ -2423,7 +2419,7 @@ static int read_partial_message(struct ceph_connection *con)
        }
 
        if (need_sign && con->ops->check_message_signature &&
-           con->ops->check_message_signature(con, m)) {
+           con->ops->check_message_signature(m)) {
                pr_err("read_partial_message %p signature check failed\n", m);
                return -EBADMSG;
        }
@@ -2438,13 +2434,10 @@ static int read_partial_message(struct ceph_connection *con)
  */
 static void process_message(struct ceph_connection *con)
 {
-       struct ceph_msg *msg;
+       struct ceph_msg *msg = con->in_msg;
 
        BUG_ON(con->in_msg->con != con);
-       con->in_msg->con = NULL;
-       msg = con->in_msg;
        con->in_msg = NULL;
-       con->ops->put(con);
 
        /* if first message, set peer_name */
        if (con->peer_name.type == 0)
@@ -2677,7 +2670,7 @@ static int try_read(struct ceph_connection *con)
                if (ret <= 0) {
                        switch (ret) {
                        case -EBADMSG:
-                               con->error_msg = "bad crc";
+                               con->error_msg = "bad crc/signature";
                                /* fall through */
                        case -EBADE:
                                ret = -EIO;
@@ -2918,10 +2911,8 @@ static void con_fault(struct ceph_connection *con)
 
        if (con->in_msg) {
                BUG_ON(con->in_msg->con != con);
-               con->in_msg->con = NULL;
                ceph_msg_put(con->in_msg);
                con->in_msg = NULL;
-               con->ops->put(con);
        }
 
        /* Requeue anything that hasn't been acked */
@@ -2952,15 +2943,8 @@ static void con_fault(struct ceph_connection *con)
  * initialize a new messenger instance
  */
 void ceph_messenger_init(struct ceph_messenger *msgr,
-                       struct ceph_entity_addr *myaddr,
-                       u64 supported_features,
-                       u64 required_features,
-                       bool nocrc,
-                       bool tcp_nodelay)
+                        struct ceph_entity_addr *myaddr)
 {
-       msgr->supported_features = supported_features;
-       msgr->required_features = required_features;
-
        spin_lock_init(&msgr->global_seq_lock);
 
        if (myaddr)
@@ -2970,8 +2954,6 @@ void ceph_messenger_init(struct ceph_messenger *msgr,
        msgr->inst.addr.type = 0;
        get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce));
        encode_my_addr(msgr);
-       msgr->nocrc = nocrc;
-       msgr->tcp_nodelay = tcp_nodelay;
 
        atomic_set(&msgr->stopping, 0);
        write_pnet(&msgr->net, get_net(current->nsproxy->net_ns));
@@ -2986,6 +2968,15 @@ void ceph_messenger_fini(struct ceph_messenger *msgr)
 }
 EXPORT_SYMBOL(ceph_messenger_fini);
 
+static void msg_con_set(struct ceph_msg *msg, struct ceph_connection *con)
+{
+       if (msg->con)
+               msg->con->ops->put(msg->con);
+
+       msg->con = con ? con->ops->get(con) : NULL;
+       BUG_ON(msg->con != con);
+}
+
 static void clear_standby(struct ceph_connection *con)
 {
        /* come back from STANDBY? */
@@ -3017,9 +3008,7 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
                return;
        }
 
-       BUG_ON(msg->con != NULL);
-       msg->con = con->ops->get(con);
-       BUG_ON(msg->con == NULL);
+       msg_con_set(msg, con);
 
        BUG_ON(!list_empty(&msg->list_head));
        list_add_tail(&msg->list_head, &con->out_queue);
@@ -3047,16 +3036,15 @@ void ceph_msg_revoke(struct ceph_msg *msg)
 {
        struct ceph_connection *con = msg->con;
 
-       if (!con)
+       if (!con) {
+               dout("%s msg %p null con\n", __func__, msg);
                return;         /* Message not in our possession */
+       }
 
        mutex_lock(&con->mutex);
        if (!list_empty(&msg->list_head)) {
                dout("%s %p msg %p - was on queue\n", __func__, con, msg);
                list_del_init(&msg->list_head);
-               BUG_ON(msg->con == NULL);
-               msg->con->ops->put(msg->con);
-               msg->con = NULL;
                msg->hdr.seq = 0;
 
                ceph_msg_put(msg);
@@ -3080,16 +3068,13 @@ void ceph_msg_revoke(struct ceph_msg *msg)
  */
 void ceph_msg_revoke_incoming(struct ceph_msg *msg)
 {
-       struct ceph_connection *con;
+       struct ceph_connection *con = msg->con;
 
-       BUG_ON(msg == NULL);
-       if (!msg->con) {
+       if (!con) {
                dout("%s msg %p null con\n", __func__, msg);
-
                return;         /* Message not in our possession */
        }
 
-       con = msg->con;
        mutex_lock(&con->mutex);
        if (con->in_msg == msg) {
                unsigned int front_len = le32_to_cpu(con->in_hdr.front_len);
@@ -3335,9 +3320,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
        }
        if (msg) {
                BUG_ON(*skip);
+               msg_con_set(msg, con);
                con->in_msg = msg;
-               con->in_msg->con = con->ops->get(con);
-               BUG_ON(con->in_msg->con == NULL);
        } else {
                /*
                 * Null message pointer means either we should skip
@@ -3384,6 +3368,8 @@ static void ceph_msg_release(struct kref *kref)
        dout("%s %p\n", __func__, m);
        WARN_ON(!list_empty(&m->list_head));
 
+       msg_con_set(m, NULL);
+
        /* drop middle, data, if any */
        if (m->middle) {
                ceph_buffer_put(m->middle);
index f79ccac6699fb7b171b680261db9000f7fe4c70c..f8f235930d887adf1df94314b18c719638328df0 100644 (file)
@@ -120,11 +120,13 @@ static void ceph_osd_data_bio_init(struct ceph_osd_data *osd_data,
 }
 #endif /* CONFIG_BLOCK */
 
-#define osd_req_op_data(oreq, whch, typ, fld)  \
-       ({                                              \
-               BUG_ON(whch >= (oreq)->r_num_ops);      \
-               &(oreq)->r_ops[whch].typ.fld;           \
-       })
+#define osd_req_op_data(oreq, whch, typ, fld)                          \
+({                                                                     \
+       struct ceph_osd_request *__oreq = (oreq);                       \
+       unsigned int __whch = (whch);                                   \
+       BUG_ON(__whch >= __oreq->r_num_ops);                            \
+       &__oreq->r_ops[__whch].typ.fld;                                 \
+})
 
 static struct ceph_osd_data *
 osd_req_op_raw_data_in(struct ceph_osd_request *osd_req, unsigned int which)
@@ -1750,8 +1752,7 @@ static void complete_request(struct ceph_osd_request *req)
  * handle osd op reply.  either call the callback if it is specified,
  * or do the completion to wake up the waiting thread.
  */
-static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
-                        struct ceph_connection *con)
+static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg)
 {
        void *p, *end;
        struct ceph_osd_request *req;
@@ -2807,7 +2808,7 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
                ceph_osdc_handle_map(osdc, msg);
                break;
        case CEPH_MSG_OSD_OPREPLY:
-               handle_reply(osdc, msg, con);
+               handle_reply(osdc, msg);
                break;
        case CEPH_MSG_WATCH_NOTIFY:
                handle_watch_notify(osdc, msg);
@@ -2849,9 +2850,6 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
                goto out;
        }
 
-       if (req->r_reply->con)
-               dout("%s revoking msg %p from old con %p\n", __func__,
-                    req->r_reply, req->r_reply->con);
        ceph_msg_revoke_incoming(req->r_reply);
 
        if (front_len > req->r_reply->front_alloc_len) {
@@ -2978,17 +2976,19 @@ static int invalidate_authorizer(struct ceph_connection *con)
        return ceph_monc_validate_auth(&osdc->client->monc);
 }
 
-static int sign_message(struct ceph_connection *con, struct ceph_msg *msg)
+static int osd_sign_message(struct ceph_msg *msg)
 {
-       struct ceph_osd *o = con->private;
+       struct ceph_osd *o = msg->con->private;
        struct ceph_auth_handshake *auth = &o->o_auth;
+
        return ceph_auth_sign_message(auth, msg);
 }
 
-static int check_message_signature(struct ceph_connection *con, struct ceph_msg *msg)
+static int osd_check_message_signature(struct ceph_msg *msg)
 {
-       struct ceph_osd *o = con->private;
+       struct ceph_osd *o = msg->con->private;
        struct ceph_auth_handshake *auth = &o->o_auth;
+
        return ceph_auth_check_message_signature(auth, msg);
 }
 
@@ -3000,7 +3000,7 @@ static const struct ceph_connection_operations osd_con_ops = {
        .verify_authorizer_reply = verify_authorizer_reply,
        .invalidate_authorizer = invalidate_authorizer,
        .alloc_msg = alloc_msg,
-       .sign_message = sign_message,
-       .check_message_signature = check_message_signature,
+       .sign_message = osd_sign_message,
+       .check_message_signature = osd_check_message_signature,
        .fault = osd_reset,
 };
index ab9b8d0d115e4ce479fed2aa8304947be09f1f32..ae00b894e67555257b1ba81dd57cecec72eed161 100644 (file)
@@ -2403,17 +2403,20 @@ static void skb_warn_bad_offload(const struct sk_buff *skb)
 {
        static const netdev_features_t null_features = 0;
        struct net_device *dev = skb->dev;
-       const char *driver = "";
+       const char *name = "";
 
        if (!net_ratelimit())
                return;
 
-       if (dev && dev->dev.parent)
-               driver = dev_driver_string(dev->dev.parent);
-
+       if (dev) {
+               if (dev->dev.parent)
+                       name = dev_driver_string(dev->dev.parent);
+               else
+                       name = netdev_name(dev);
+       }
        WARN(1, "%s: caps=(%pNF, %pNF) len=%d data_len=%d gso_size=%d "
             "gso_type=%d ip_summed=%d\n",
-            driver, dev ? &dev->features : &null_features,
+            name, dev ? &dev->features : &null_features,
             skb->sk ? &skb->sk->sk_route_caps : &null_features,
             skb->len, skb->data_len, skb_shinfo(skb)->gso_size,
             skb_shinfo(skb)->gso_type, skb->ip_summed);
@@ -6426,11 +6429,16 @@ int __netdev_update_features(struct net_device *dev)
 
        if (dev->netdev_ops->ndo_set_features)
                err = dev->netdev_ops->ndo_set_features(dev, features);
+       else
+               err = 0;
 
        if (unlikely(err < 0)) {
                netdev_err(dev,
                        "set_features() failed (%d); wanted %pNF, left %pNF\n",
                        err, &features, &dev->features);
+               /* return non-0 since some features might have changed and
+                * it's better to fire a spurious notification than miss it
+                */
                return -1;
        }
 
index 1aa8437ed6c4437d196ad513f0d3619198914416..e6af42da28d9552643751a1af7dfcd96cad05c3d 100644 (file)
@@ -857,7 +857,7 @@ static void neigh_probe(struct neighbour *neigh)
        struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
        /* keep skb alive even if arp_queue overflows */
        if (skb)
-               skb = skb_copy(skb, GFP_ATOMIC);
+               skb = skb_clone(skb, GFP_ATOMIC);
        write_unlock(&neigh->lock);
        neigh->ops->solicit(neigh, skb);
        atomic_inc(&neigh->probes);
index 504bd17b7456c3a16a0832ed28ede040c41ff316..34ba7a08876de74409ea5d2ad3af6f78124ff0a7 100644 (file)
@@ -1045,15 +1045,156 @@ static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb,
+                                             struct net_device *dev)
+{
+       const struct rtnl_link_stats64 *stats;
+       struct rtnl_link_stats64 temp;
+       struct nlattr *attr;
+
+       stats = dev_get_stats(dev, &temp);
+
+       attr = nla_reserve(skb, IFLA_STATS,
+                          sizeof(struct rtnl_link_stats));
+       if (!attr)
+               return -EMSGSIZE;
+
+       copy_rtnl_link_stats(nla_data(attr), stats);
+
+       attr = nla_reserve(skb, IFLA_STATS64,
+                          sizeof(struct rtnl_link_stats64));
+       if (!attr)
+               return -EMSGSIZE;
+
+       copy_rtnl_link_stats64(nla_data(attr), stats);
+
+       return 0;
+}
+
+static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
+                                              struct net_device *dev,
+                                              int vfs_num,
+                                              struct nlattr *vfinfo)
+{
+       struct ifla_vf_rss_query_en vf_rss_query_en;
+       struct ifla_vf_link_state vf_linkstate;
+       struct ifla_vf_spoofchk vf_spoofchk;
+       struct ifla_vf_tx_rate vf_tx_rate;
+       struct ifla_vf_stats vf_stats;
+       struct ifla_vf_trust vf_trust;
+       struct ifla_vf_vlan vf_vlan;
+       struct ifla_vf_rate vf_rate;
+       struct nlattr *vf, *vfstats;
+       struct ifla_vf_mac vf_mac;
+       struct ifla_vf_info ivi;
+
+       /* Not all SR-IOV capable drivers support the
+        * spoofcheck and "RSS query enable" query.  Preset to
+        * -1 so the user space tool can detect that the driver
+        * didn't report anything.
+        */
+       ivi.spoofchk = -1;
+       ivi.rss_query_en = -1;
+       ivi.trusted = -1;
+       memset(ivi.mac, 0, sizeof(ivi.mac));
+       /* The default value for VF link state is "auto"
+        * IFLA_VF_LINK_STATE_AUTO which equals zero
+        */
+       ivi.linkstate = 0;
+       if (dev->netdev_ops->ndo_get_vf_config(dev, vfs_num, &ivi))
+               return 0;
+
+       vf_mac.vf =
+               vf_vlan.vf =
+               vf_rate.vf =
+               vf_tx_rate.vf =
+               vf_spoofchk.vf =
+               vf_linkstate.vf =
+               vf_rss_query_en.vf =
+               vf_trust.vf = ivi.vf;
+
+       memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+       vf_vlan.vlan = ivi.vlan;
+       vf_vlan.qos = ivi.qos;
+       vf_tx_rate.rate = ivi.max_tx_rate;
+       vf_rate.min_tx_rate = ivi.min_tx_rate;
+       vf_rate.max_tx_rate = ivi.max_tx_rate;
+       vf_spoofchk.setting = ivi.spoofchk;
+       vf_linkstate.link_state = ivi.linkstate;
+       vf_rss_query_en.setting = ivi.rss_query_en;
+       vf_trust.setting = ivi.trusted;
+       vf = nla_nest_start(skb, IFLA_VF_INFO);
+       if (!vf) {
+               nla_nest_cancel(skb, vfinfo);
+               return -EMSGSIZE;
+       }
+       if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
+           nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
+           nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
+                   &vf_rate) ||
+           nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
+                   &vf_tx_rate) ||
+           nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
+                   &vf_spoofchk) ||
+           nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
+                   &vf_linkstate) ||
+           nla_put(skb, IFLA_VF_RSS_QUERY_EN,
+                   sizeof(vf_rss_query_en),
+                   &vf_rss_query_en) ||
+           nla_put(skb, IFLA_VF_TRUST,
+                   sizeof(vf_trust), &vf_trust))
+               return -EMSGSIZE;
+       memset(&vf_stats, 0, sizeof(vf_stats));
+       if (dev->netdev_ops->ndo_get_vf_stats)
+               dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
+                                               &vf_stats);
+       vfstats = nla_nest_start(skb, IFLA_VF_STATS);
+       if (!vfstats) {
+               nla_nest_cancel(skb, vf);
+               nla_nest_cancel(skb, vfinfo);
+               return -EMSGSIZE;
+       }
+       if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
+                       vf_stats.rx_packets) ||
+           nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
+                       vf_stats.tx_packets) ||
+           nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
+                       vf_stats.rx_bytes) ||
+           nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
+                       vf_stats.tx_bytes) ||
+           nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
+                       vf_stats.broadcast) ||
+           nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
+                       vf_stats.multicast))
+               return -EMSGSIZE;
+       nla_nest_end(skb, vfstats);
+       nla_nest_end(skb, vf);
+       return 0;
+}
+
+static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
+{
+       struct rtnl_link_ifmap map = {
+               .mem_start   = dev->mem_start,
+               .mem_end     = dev->mem_end,
+               .base_addr   = dev->base_addr,
+               .irq         = dev->irq,
+               .dma         = dev->dma,
+               .port        = dev->if_port,
+       };
+       if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask)
 {
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
-       struct rtnl_link_stats64 temp;
-       const struct rtnl_link_stats64 *stats;
-       struct nlattr *attr, *af_spec;
+       struct nlattr *af_spec;
        struct rtnl_af_ops *af_ops;
        struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
 
@@ -1096,18 +1237,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
            nla_put_u8(skb, IFLA_PROTO_DOWN, dev->proto_down))
                goto nla_put_failure;
 
-       if (1) {
-               struct rtnl_link_ifmap map = {
-                       .mem_start   = dev->mem_start,
-                       .mem_end     = dev->mem_end,
-                       .base_addr   = dev->base_addr,
-                       .irq         = dev->irq,
-                       .dma         = dev->dma,
-                       .port        = dev->if_port,
-               };
-               if (nla_put(skb, IFLA_MAP, sizeof(map), &map))
-                       goto nla_put_failure;
-       }
+       if (rtnl_fill_link_ifmap(skb, dev))
+               goto nla_put_failure;
 
        if (dev->addr_len) {
                if (nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr) ||
@@ -1124,128 +1255,27 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        if (rtnl_phys_switch_id_fill(skb, dev))
                goto nla_put_failure;
 
-       attr = nla_reserve(skb, IFLA_STATS,
-                       sizeof(struct rtnl_link_stats));
-       if (attr == NULL)
-               goto nla_put_failure;
-
-       stats = dev_get_stats(dev, &temp);
-       copy_rtnl_link_stats(nla_data(attr), stats);
-
-       attr = nla_reserve(skb, IFLA_STATS64,
-                       sizeof(struct rtnl_link_stats64));
-       if (attr == NULL)
+       if (rtnl_fill_stats(skb, dev))
                goto nla_put_failure;
-       copy_rtnl_link_stats64(nla_data(attr), stats);
 
        if (dev->dev.parent && (ext_filter_mask & RTEXT_FILTER_VF) &&
            nla_put_u32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)))
                goto nla_put_failure;
 
-       if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent
-           && (ext_filter_mask & RTEXT_FILTER_VF)) {
+       if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent &&
+           ext_filter_mask & RTEXT_FILTER_VF) {
                int i;
-
-               struct nlattr *vfinfo, *vf, *vfstats;
+               struct nlattr *vfinfo;
                int num_vfs = dev_num_vf(dev->dev.parent);
 
                vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
                if (!vfinfo)
                        goto nla_put_failure;
                for (i = 0; i < num_vfs; i++) {
-                       struct ifla_vf_info ivi;
-                       struct ifla_vf_mac vf_mac;
-                       struct ifla_vf_vlan vf_vlan;
-                       struct ifla_vf_rate vf_rate;
-                       struct ifla_vf_tx_rate vf_tx_rate;
-                       struct ifla_vf_spoofchk vf_spoofchk;
-                       struct ifla_vf_link_state vf_linkstate;
-                       struct ifla_vf_rss_query_en vf_rss_query_en;
-                       struct ifla_vf_stats vf_stats;
-                       struct ifla_vf_trust vf_trust;
-
-                       /*
-                        * Not all SR-IOV capable drivers support the
-                        * spoofcheck and "RSS query enable" query.  Preset to
-                        * -1 so the user space tool can detect that the driver
-                        * didn't report anything.
-                        */
-                       ivi.spoofchk = -1;
-                       ivi.rss_query_en = -1;
-                       ivi.trusted = -1;
-                       memset(ivi.mac, 0, sizeof(ivi.mac));
-                       /* The default value for VF link state is "auto"
-                        * IFLA_VF_LINK_STATE_AUTO which equals zero
-                        */
-                       ivi.linkstate = 0;
-                       if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
-                               break;
-                       vf_mac.vf =
-                               vf_vlan.vf =
-                               vf_rate.vf =
-                               vf_tx_rate.vf =
-                               vf_spoofchk.vf =
-                               vf_linkstate.vf =
-                               vf_rss_query_en.vf =
-                               vf_trust.vf = ivi.vf;
-
-                       memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
-                       vf_vlan.vlan = ivi.vlan;
-                       vf_vlan.qos = ivi.qos;
-                       vf_tx_rate.rate = ivi.max_tx_rate;
-                       vf_rate.min_tx_rate = ivi.min_tx_rate;
-                       vf_rate.max_tx_rate = ivi.max_tx_rate;
-                       vf_spoofchk.setting = ivi.spoofchk;
-                       vf_linkstate.link_state = ivi.linkstate;
-                       vf_rss_query_en.setting = ivi.rss_query_en;
-                       vf_trust.setting = ivi.trusted;
-                       vf = nla_nest_start(skb, IFLA_VF_INFO);
-                       if (!vf) {
-                               nla_nest_cancel(skb, vfinfo);
-                               goto nla_put_failure;
-                       }
-                       if (nla_put(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac) ||
-                           nla_put(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan) ||
-                           nla_put(skb, IFLA_VF_RATE, sizeof(vf_rate),
-                                   &vf_rate) ||
-                           nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate),
-                                   &vf_tx_rate) ||
-                           nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk),
-                                   &vf_spoofchk) ||
-                           nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate),
-                                   &vf_linkstate) ||
-                           nla_put(skb, IFLA_VF_RSS_QUERY_EN,
-                                   sizeof(vf_rss_query_en),
-                                   &vf_rss_query_en) ||
-                           nla_put(skb, IFLA_VF_TRUST,
-                                   sizeof(vf_trust), &vf_trust))
+                       if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
                                goto nla_put_failure;
-                       memset(&vf_stats, 0, sizeof(vf_stats));
-                       if (dev->netdev_ops->ndo_get_vf_stats)
-                               dev->netdev_ops->ndo_get_vf_stats(dev, i,
-                                                                 &vf_stats);
-                       vfstats = nla_nest_start(skb, IFLA_VF_STATS);
-                       if (!vfstats) {
-                               nla_nest_cancel(skb, vf);
-                               nla_nest_cancel(skb, vfinfo);
-                               goto nla_put_failure;
-                       }
-                       if (nla_put_u64(skb, IFLA_VF_STATS_RX_PACKETS,
-                                       vf_stats.rx_packets) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_TX_PACKETS,
-                                       vf_stats.tx_packets) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_RX_BYTES,
-                                       vf_stats.rx_bytes) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_TX_BYTES,
-                                       vf_stats.tx_bytes) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_BROADCAST,
-                                       vf_stats.broadcast) ||
-                           nla_put_u64(skb, IFLA_VF_STATS_MULTICAST,
-                                       vf_stats.multicast))
-                               goto nla_put_failure;
-                       nla_nest_end(skb, vfstats);
-                       nla_nest_end(skb, vf);
                }
+
                nla_nest_end(skb, vfinfo);
        }
 
index aa41e6dd642913f2181832145e22ec1dad6fa7b8..152b9c70e25255f1c104c00db3867fd6b21bfa99 100644 (file)
@@ -4268,7 +4268,8 @@ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
                return NULL;
        }
 
-       memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
+       memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len,
+               2 * ETH_ALEN);
        skb->mac_header += VLAN_HLEN;
        return skb;
 }
index 1feb15f23de8c4f673fd0fe713df2dd9195995cf..46b9c887bede0568ec378d3b809dda8fa463a166 100644 (file)
@@ -563,7 +563,7 @@ static void reqsk_timer_handler(unsigned long data)
        int max_retries, thresh;
        u8 defer_accept;
 
-       if (sk_listener->sk_state != TCP_LISTEN)
+       if (sk_state_load(sk_listener) != TCP_LISTEN)
                goto drop;
 
        max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries;
@@ -749,7 +749,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog)
         * It is OK, because this socket enters to hash table only
         * after validation is complete.
         */
-       sk->sk_state = TCP_LISTEN;
+       sk_state_store(sk, TCP_LISTEN);
        if (!sk->sk_prot->get_port(sk, inet->inet_num)) {
                inet->inet_sport = htons(inet->inet_num);
 
index 657d2307f031e7fb2a2e38f763cf528329931614..b3ca21b2ba9b638550b552c85e297234ccf39caa 100644 (file)
@@ -45,7 +45,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
        struct net *net = nf_ct_net(ct);
        const struct nf_conn *master = ct->master;
        struct nf_conntrack_expect *other_exp;
-       struct nf_conntrack_tuple t;
+       struct nf_conntrack_tuple t = {};
        const struct nf_ct_pptp_master *ct_pptp_info;
        const struct nf_nat_pptp *nat_pptp_info;
        struct nf_nat_range range;
index 8c0d0bdc2a7c59ad44752f2d378a07d505753a8b..63e5be0abd86ddab6476221161c48aacef34d8c4 100644 (file)
@@ -406,10 +406,12 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                        ip_select_ident(net, skb, NULL);
 
                iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+               skb->transport_header += iphlen;
+               if (iph->protocol == IPPROTO_ICMP &&
+                   length >= iphlen + sizeof(struct icmphdr))
+                       icmp_out_count(net, ((struct icmphdr *)
+                               skb_transport_header(skb))->type);
        }
-       if (iph->protocol == IPPROTO_ICMP)
-               icmp_out_count(net, ((struct icmphdr *)
-                       skb_transport_header(skb))->type);
 
        err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
                      net, sk, skb, NULL, rt->dst.dev,
index 0cfa7c0c1e80dae18b3aa51c3d71d021dd8b4f84..c1728771cf89c46a82af0187a02029450adb854b 100644 (file)
@@ -451,11 +451,14 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        unsigned int mask;
        struct sock *sk = sock->sk;
        const struct tcp_sock *tp = tcp_sk(sk);
+       int state;
 
        sock_rps_record_flow(sk);
 
        sock_poll_wait(file, sk_sleep(sk), wait);
-       if (sk->sk_state == TCP_LISTEN)
+
+       state = sk_state_load(sk);
+       if (state == TCP_LISTEN)
                return inet_csk_listen_poll(sk);
 
        /* Socket is not locked. We are protected from async events
@@ -492,14 +495,14 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
         * NOTE. Check for TCP_CLOSE is added. The goal is to prevent
         * blocking on fresh not-connected or disconnected socket. --ANK
         */
-       if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == TCP_CLOSE)
+       if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
                mask |= POLLHUP;
        if (sk->sk_shutdown & RCV_SHUTDOWN)
                mask |= POLLIN | POLLRDNORM | POLLRDHUP;
 
        /* Connected or passive Fast Open socket? */
-       if (sk->sk_state != TCP_SYN_SENT &&
-           (sk->sk_state != TCP_SYN_RECV || tp->fastopen_rsk)) {
+       if (state != TCP_SYN_SENT &&
+           (state != TCP_SYN_RECV || tp->fastopen_rsk)) {
                int target = sock_rcvlowat(sk, 0, INT_MAX);
 
                if (tp->urg_seq == tp->copied_seq &&
@@ -507,9 +510,6 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
                    tp->urg_data)
                        target++;
 
-               /* Potential race condition. If read of tp below will
-                * escape above sk->sk_state, we can be illegally awaken
-                * in SYN_* states. */
                if (tp->rcv_nxt - tp->copied_seq >= target)
                        mask |= POLLIN | POLLRDNORM;
 
@@ -1934,7 +1934,7 @@ void tcp_set_state(struct sock *sk, int state)
        /* Change state AFTER socket is unhashed to avoid closed
         * socket sitting in hash tables.
         */
-       sk->sk_state = state;
+       sk_state_store(sk, state);
 
 #ifdef STATE_TRACE
        SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n", sk, statename[oldstate], statename[state]);
@@ -2644,7 +2644,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        if (sk->sk_type != SOCK_STREAM)
                return;
 
-       info->tcpi_state = sk->sk_state;
+       info->tcpi_state = sk_state_load(sk);
+
        info->tcpi_ca_state = icsk->icsk_ca_state;
        info->tcpi_retransmits = icsk->icsk_retransmits;
        info->tcpi_probes = icsk->icsk_probes_out;
@@ -2672,7 +2673,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
        info->tcpi_snd_mss = tp->mss_cache;
        info->tcpi_rcv_mss = icsk->icsk_ack.rcv_mss;
 
-       if (sk->sk_state == TCP_LISTEN) {
+       if (info->tcpi_state == TCP_LISTEN) {
                info->tcpi_unacked = sk->sk_ack_backlog;
                info->tcpi_sacked = sk->sk_max_ack_backlog;
        } else {
index 479f34946177eb3f65d9dfa2f3930a0ce2faad65..b31604086edd6b8aec2eaaf67c755b63caf75743 100644 (file)
@@ -21,7 +21,7 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
 {
        struct tcp_info *info = _info;
 
-       if (sk->sk_state == TCP_LISTEN) {
+       if (sk_state_load(sk) == TCP_LISTEN) {
                r->idiag_rqueue = sk->sk_ack_backlog;
                r->idiag_wqueue = sk->sk_max_ack_backlog;
        } else if (sk->sk_type == SOCK_STREAM) {
index 950e28c0cdf25e23658926cdcf37335aed3fb193..ba09016d1bfd2a778d57cdc37f0a7db539f9cb3a 100644 (file)
@@ -2158,6 +2158,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
        __u16 destp = ntohs(inet->inet_dport);
        __u16 srcp = ntohs(inet->inet_sport);
        int rx_queue;
+       int state;
 
        if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
            icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
@@ -2175,17 +2176,18 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
                timer_expires = jiffies;
        }
 
-       if (sk->sk_state == TCP_LISTEN)
+       state = sk_state_load(sk);
+       if (state == TCP_LISTEN)
                rx_queue = sk->sk_ack_backlog;
        else
-               /*
-                * because we dont lock socket, we might find a transient negative value
+               /* Because we don't lock the socket,
+                * we might find a transient negative value.
                 */
                rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
 
        seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
                        "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d",
-               i, src, srcp, dest, destp, sk->sk_state,
+               i, src, srcp, dest, destp, state,
                tp->write_seq - tp->snd_una,
                rx_queue,
                timer_active,
@@ -2199,8 +2201,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
                jiffies_to_clock_t(icsk->icsk_ack.ato),
                (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                tp->snd_cwnd,
-               sk->sk_state == TCP_LISTEN ?
-                   (fastopenq ? fastopenq->max_qlen : 0) :
+               state == TCP_LISTEN ?
+                   fastopenq->max_qlen :
                    (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh));
 }
 
index 124338a39e29cb3e3a5e602fb706486f330fb529..5ee56d0a8699e22434d5ad8b4380f890fa8d2126 100644 (file)
@@ -1651,7 +1651,6 @@ static void mld_sendpack(struct sk_buff *skb)
        if (!err) {
                ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-               IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
        } else {
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
        }
@@ -2015,7 +2014,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
        if (!err) {
                ICMP6MSGOUT_INC_STATS(net, idev, type);
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-               IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len);
        } else
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
index c8bc9b4ac32835e7328025a8912f3627b365e38a..6f01fe122abd7c0348bfcd67d1a55ecb40f1c0b0 100644 (file)
@@ -404,6 +404,14 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        }
 }
 
+static bool __rt6_check_expired(const struct rt6_info *rt)
+{
+       if (rt->rt6i_flags & RTF_EXPIRES)
+               return time_after(jiffies, rt->dst.expires);
+       else
+               return false;
+}
+
 static bool rt6_check_expired(const struct rt6_info *rt)
 {
        if (rt->rt6i_flags & RTF_EXPIRES) {
@@ -1252,7 +1260,8 @@ static struct dst_entry *rt6_check(struct rt6_info *rt, u32 cookie)
 
 static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt, u32 cookie)
 {
-       if (rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
+       if (!__rt6_check_expired(rt) &&
+           rt->dst.obsolete == DST_OBSOLETE_FORCE_CHK &&
            rt6_check((struct rt6_info *)(rt->dst.from), cookie))
                return &rt->dst;
        else
@@ -1272,7 +1281,8 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
        rt6_dst_from_metrics_check(rt);
 
-       if ((rt->rt6i_flags & RTF_PCPU) || unlikely(dst->flags & DST_NOCACHE))
+       if (rt->rt6i_flags & RTF_PCPU ||
+           (unlikely(dst->flags & DST_NOCACHE) && rt->dst.from))
                return rt6_dst_from_check(rt, cookie);
        else
                return rt6_check(rt, cookie);
@@ -1322,6 +1332,12 @@ static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)
        rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
 }
 
+static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
+{
+       return !(rt->rt6i_flags & RTF_CACHE) &&
+               (rt->rt6i_flags & RTF_PCPU || rt->rt6i_node);
+}
+
 static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
                                 const struct ipv6hdr *iph, u32 mtu)
 {
@@ -1335,7 +1351,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
        if (mtu >= dst_mtu(dst))
                return;
 
-       if (rt6->rt6i_flags & RTF_CACHE) {
+       if (!rt6_cache_allowed_for_pmtu(rt6)) {
                rt6_do_update_pmtu(rt6, mtu);
        } else {
                const struct in6_addr *daddr, *saddr;
index 5baa8e754e412c454ca22c03822cc57c29df8c35..c5429a636f1aef539d0ea6bb27f585a3297b7769 100644 (file)
@@ -1690,6 +1690,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
        const struct tcp_sock *tp = tcp_sk(sp);
        const struct inet_connection_sock *icsk = inet_csk(sp);
        const struct fastopen_queue *fastopenq = &icsk->icsk_accept_queue.fastopenq;
+       int rx_queue;
+       int state;
 
        dest  = &sp->sk_v6_daddr;
        src   = &sp->sk_v6_rcv_saddr;
@@ -1710,6 +1712,15 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                timer_expires = jiffies;
        }
 
+       state = sk_state_load(sp);
+       if (state == TCP_LISTEN)
+               rx_queue = sp->sk_ack_backlog;
+       else
+               /* Because we don't lock the socket,
+                * we might find a transient negative value.
+                */
+               rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
+
        seq_printf(seq,
                   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
                   "%02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %lu %lu %u %u %d\n",
@@ -1718,9 +1729,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   src->s6_addr32[2], src->s6_addr32[3], srcp,
                   dest->s6_addr32[0], dest->s6_addr32[1],
                   dest->s6_addr32[2], dest->s6_addr32[3], destp,
-                  sp->sk_state,
-                  tp->write_seq-tp->snd_una,
-                  (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
+                  state,
+                  tp->write_seq - tp->snd_una,
+                  rx_queue,
                   timer_active,
                   jiffies_delta_to_clock_t(timer_expires - jiffies),
                   icsk->icsk_retransmits,
@@ -1732,7 +1743,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   jiffies_to_clock_t(icsk->icsk_ack.ato),
                   (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                   tp->snd_cwnd,
-                  sp->sk_state == TCP_LISTEN ?
+                  state == TCP_LISTEN ?
                        fastopenq->max_qlen :
                        (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh)
                   );
index e22349ea725605a05ce03cb3701142856daf420c..4692782b528053a408b15f0daccaf6f6cb3fc10e 100644 (file)
@@ -869,7 +869,7 @@ config NETFILTER_XT_TARGET_TEE
        depends on IPV6 || IPV6=n
        depends on !NF_CONNTRACK || NF_CONNTRACK
        select NF_DUP_IPV4
-       select NF_DUP_IPV6 if IP6_NF_IPTABLES
+       select NF_DUP_IPV6 if IP6_NF_IPTABLES != n
        ---help---
        This option adds a "TEE" target with which a packet can be cloned and
        this clone be rerouted to another nexthop.
@@ -882,7 +882,7 @@ config NETFILTER_XT_TARGET_TPROXY
        depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n
        depends on IP_NF_MANGLE
        select NF_DEFRAG_IPV4
-       select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
+       select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n
        help
          This option adds a `TPROXY' target, which is somewhat similar to
          REDIRECT.  It can only be used in the mangle table and is useful
@@ -1375,7 +1375,7 @@ config NETFILTER_XT_MATCH_SOCKET
        depends on IPV6 || IPV6=n
        depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n
        select NF_DEFRAG_IPV4
-       select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES
+       select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n
        help
          This option adds a `socket' match, which can be used to match
          packets for which a TCP or UDP socket lookup finds a valid socket.
index d05e759ed0fafe62ef299e6f097f0d18f08ec567..b0bc475f641e3b2c808f78f5be54283de6866d25 100644 (file)
@@ -33,7 +33,7 @@
 #define mtype_gc               IPSET_TOKEN(MTYPE, _gc)
 #define mtype                  MTYPE
 
-#define get_ext(set, map, id)  ((map)->extensions + (set)->dsize * (id))
+#define get_ext(set, map, id)  ((map)->extensions + ((set)->dsize * (id)))
 
 static void
 mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
@@ -67,12 +67,9 @@ mtype_destroy(struct ip_set *set)
                del_timer_sync(&map->gc);
 
        ip_set_free(map->members);
-       if (set->dsize) {
-               if (set->extensions & IPSET_EXT_DESTROY)
-                       mtype_ext_cleanup(set);
-               ip_set_free(map->extensions);
-       }
-       kfree(map);
+       if (set->dsize && set->extensions & IPSET_EXT_DESTROY)
+               mtype_ext_cleanup(set);
+       ip_set_free(map);
 
        set->data = NULL;
 }
@@ -92,16 +89,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
 {
        const struct mtype *map = set->data;
        struct nlattr *nested;
+       size_t memsize = sizeof(*map) + map->memsize;
 
        nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
        if (!nested)
                goto nla_put_failure;
        if (mtype_do_head(skb, map) ||
            nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
-           nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
-                         htonl(sizeof(*map) +
-                               map->memsize +
-                               set->dsize * map->elements)))
+           nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)))
                goto nla_put_failure;
        if (unlikely(ip_set_put_flags(skb, set)))
                goto nla_put_failure;
index 64a5643344180d813e3b3fc914c1b1c93dcd58be..4783efff0bde6b7c70707c8153563669308d995a 100644 (file)
@@ -41,7 +41,6 @@ MODULE_ALIAS("ip_set_bitmap:ip");
 /* Type structure */
 struct bitmap_ip {
        void *members;          /* the set members */
-       void *extensions;       /* data extensions */
        u32 first_ip;           /* host byte order, included in range */
        u32 last_ip;            /* host byte order, included in range */
        u32 elements;           /* number of max elements in the set */
@@ -49,6 +48,8 @@ struct bitmap_ip {
        size_t memsize;         /* members size */
        u8 netmask;             /* subnet netmask */
        struct timer_list gc;   /* garbage collection */
+       unsigned char extensions[0]     /* data extensions */
+               __aligned(__alignof__(u64));
 };
 
 /* ADT structure for generic function args */
@@ -224,13 +225,6 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
        map->members = ip_set_alloc(map->memsize);
        if (!map->members)
                return false;
-       if (set->dsize) {
-               map->extensions = ip_set_alloc(set->dsize * elements);
-               if (!map->extensions) {
-                       kfree(map->members);
-                       return false;
-               }
-       }
        map->first_ip = first_ip;
        map->last_ip = last_ip;
        map->elements = elements;
@@ -316,13 +310,13 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        pr_debug("hosts %u, elements %llu\n",
                 hosts, (unsigned long long)elements);
 
-       map = kzalloc(sizeof(*map), GFP_KERNEL);
+       set->dsize = ip_set_elem_len(set, tb, 0, 0);
+       map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
        if (!map)
                return -ENOMEM;
 
        map->memsize = bitmap_bytes(0, elements - 1);
        set->variant = &bitmap_ip;
-       set->dsize = ip_set_elem_len(set, tb, 0);
        if (!init_map_ip(set, map, first_ip, last_ip,
                         elements, hosts, netmask)) {
                kfree(map);
index 1430535118fb0d9c23c1f05c72e75034c1953cd7..29dde208381dac6cdfca67094dc4fc07bc85b40c 100644 (file)
@@ -47,24 +47,26 @@ enum {
 /* Type structure */
 struct bitmap_ipmac {
        void *members;          /* the set members */
-       void *extensions;       /* MAC + data extensions */
        u32 first_ip;           /* host byte order, included in range */
        u32 last_ip;            /* host byte order, included in range */
        u32 elements;           /* number of max elements in the set */
        size_t memsize;         /* members size */
        struct timer_list gc;   /* garbage collector */
+       unsigned char extensions[0]     /* MAC + data extensions */
+               __aligned(__alignof__(u64));
 };
 
 /* ADT structure for generic function args */
 struct bitmap_ipmac_adt_elem {
+       unsigned char ether[ETH_ALEN] __aligned(2);
        u16 id;
-       unsigned char *ether;
+       u16 add_mac;
 };
 
 struct bitmap_ipmac_elem {
        unsigned char ether[ETH_ALEN];
        unsigned char filled;
-} __attribute__ ((aligned));
+} __aligned(__alignof__(u64));
 
 static inline u32
 ip_to_id(const struct bitmap_ipmac *m, u32 ip)
@@ -72,11 +74,11 @@ ip_to_id(const struct bitmap_ipmac *m, u32 ip)
        return ip - m->first_ip;
 }
 
-static inline struct bitmap_ipmac_elem *
-get_elem(void *extensions, u16 id, size_t dsize)
-{
-       return (struct bitmap_ipmac_elem *)(extensions + id * dsize);
-}
+#define get_elem(extensions, id, dsize)                \
+       (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
+
+#define get_const_elem(extensions, id, dsize)  \
+       (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
 
 /* Common functions */
 
@@ -88,10 +90,9 @@ bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
 
        if (!test_bit(e->id, map->members))
                return 0;
-       elem = get_elem(map->extensions, e->id, dsize);
-       if (elem->filled == MAC_FILLED)
-               return !e->ether ||
-                      ether_addr_equal(e->ether, elem->ether);
+       elem = get_const_elem(map->extensions, e->id, dsize);
+       if (e->add_mac && elem->filled == MAC_FILLED)
+               return ether_addr_equal(e->ether, elem->ether);
        /* Trigger kernel to fill out the ethernet address */
        return -EAGAIN;
 }
@@ -103,7 +104,7 @@ bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
 
        if (!test_bit(id, map->members))
                return 0;
-       elem = get_elem(map->extensions, id, dsize);
+       elem = get_const_elem(map->extensions, id, dsize);
        /* Timer not started for the incomplete elements */
        return elem->filled == MAC_FILLED;
 }
@@ -133,7 +134,7 @@ bitmap_ipmac_add_timeout(unsigned long *timeout,
                 * and we can reuse it later when MAC is filled out,
                 * possibly by the kernel
                 */
-               if (e->ether)
+               if (e->add_mac)
                        ip_set_timeout_set(timeout, t);
                else
                        *timeout = t;
@@ -150,7 +151,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
        elem = get_elem(map->extensions, e->id, dsize);
        if (test_bit(e->id, map->members)) {
                if (elem->filled == MAC_FILLED) {
-                       if (e->ether &&
+                       if (e->add_mac &&
                            (flags & IPSET_FLAG_EXIST) &&
                            !ether_addr_equal(e->ether, elem->ether)) {
                                /* memcpy isn't atomic */
@@ -159,7 +160,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
                                ether_addr_copy(elem->ether, e->ether);
                        }
                        return IPSET_ADD_FAILED;
-               } else if (!e->ether)
+               } else if (!e->add_mac)
                        /* Already added without ethernet address */
                        return IPSET_ADD_FAILED;
                /* Fill the MAC address and trigger the timer activation */
@@ -168,7 +169,7 @@ bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
                ether_addr_copy(elem->ether, e->ether);
                elem->filled = MAC_FILLED;
                return IPSET_ADD_START_STORED_TIMEOUT;
-       } else if (e->ether) {
+       } else if (e->add_mac) {
                /* We can store MAC too */
                ether_addr_copy(elem->ether, e->ether);
                elem->filled = MAC_FILLED;
@@ -191,7 +192,7 @@ bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
                     u32 id, size_t dsize)
 {
        const struct bitmap_ipmac_elem *elem =
-               get_elem(map->extensions, id, dsize);
+               get_const_elem(map->extensions, id, dsize);
 
        return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
                               htonl(map->first_ip + id)) ||
@@ -213,7 +214,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 {
        struct bitmap_ipmac *map = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
-       struct bitmap_ipmac_adt_elem e = { .id = 0 };
+       struct bitmap_ipmac_adt_elem e = { .id = 0, .add_mac = 1 };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
        u32 ip;
 
@@ -231,7 +232,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
                return -EINVAL;
 
        e.id = ip_to_id(map, ip);
-       e.ether = eth_hdr(skb)->h_source;
+       memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
 
        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 }
@@ -265,11 +266,10 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
                return -IPSET_ERR_BITMAP_RANGE;
 
        e.id = ip_to_id(map, ip);
-       if (tb[IPSET_ATTR_ETHER])
-               e.ether = nla_data(tb[IPSET_ATTR_ETHER]);
-       else
-               e.ether = NULL;
-
+       if (tb[IPSET_ATTR_ETHER]) {
+               memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
+               e.add_mac = 1;
+       }
        ret = adtfn(set, &e, &ext, &ext, flags);
 
        return ip_set_eexist(ret, flags) ? 0 : ret;
@@ -300,13 +300,6 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
        map->members = ip_set_alloc(map->memsize);
        if (!map->members)
                return false;
-       if (set->dsize) {
-               map->extensions = ip_set_alloc(set->dsize * elements);
-               if (!map->extensions) {
-                       kfree(map->members);
-                       return false;
-               }
-       }
        map->first_ip = first_ip;
        map->last_ip = last_ip;
        map->elements = elements;
@@ -361,14 +354,15 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
        if (elements > IPSET_BITMAP_MAX_RANGE + 1)
                return -IPSET_ERR_BITMAP_RANGE_SIZE;
 
-       map = kzalloc(sizeof(*map), GFP_KERNEL);
+       set->dsize = ip_set_elem_len(set, tb,
+                                    sizeof(struct bitmap_ipmac_elem),
+                                    __alignof__(struct bitmap_ipmac_elem));
+       map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
        if (!map)
                return -ENOMEM;
 
        map->memsize = bitmap_bytes(0, elements - 1);
        set->variant = &bitmap_ipmac;
-       set->dsize = ip_set_elem_len(set, tb,
-                                    sizeof(struct bitmap_ipmac_elem));
        if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
                kfree(map);
                return -ENOMEM;
index 5338ccd5da461eea08142479fd8315a208fc50c4..7f0c733358a428225e15afe611aad1edcd52812a 100644 (file)
@@ -35,12 +35,13 @@ MODULE_ALIAS("ip_set_bitmap:port");
 /* Type structure */
 struct bitmap_port {
        void *members;          /* the set members */
-       void *extensions;       /* data extensions */
        u16 first_port;         /* host byte order, included in range */
        u16 last_port;          /* host byte order, included in range */
        u32 elements;           /* number of max elements in the set */
        size_t memsize;         /* members size */
        struct timer_list gc;   /* garbage collection */
+       unsigned char extensions[0]     /* data extensions */
+               __aligned(__alignof__(u64));
 };
 
 /* ADT structure for generic function args */
@@ -209,13 +210,6 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
        map->members = ip_set_alloc(map->memsize);
        if (!map->members)
                return false;
-       if (set->dsize) {
-               map->extensions = ip_set_alloc(set->dsize * map->elements);
-               if (!map->extensions) {
-                       kfree(map->members);
-                       return false;
-               }
-       }
        map->first_port = first_port;
        map->last_port = last_port;
        set->timeout = IPSET_NO_TIMEOUT;
@@ -232,6 +226,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
 {
        struct bitmap_port *map;
        u16 first_port, last_port;
+       u32 elements;
 
        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
@@ -248,14 +243,15 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
                last_port = tmp;
        }
 
-       map = kzalloc(sizeof(*map), GFP_KERNEL);
+       elements = last_port - first_port + 1;
+       set->dsize = ip_set_elem_len(set, tb, 0, 0);
+       map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
        if (!map)
                return -ENOMEM;
 
-       map->elements = last_port - first_port + 1;
+       map->elements = elements;
        map->memsize = bitmap_bytes(0, map->elements);
        set->variant = &bitmap_port;
-       set->dsize = ip_set_elem_len(set, tb, 0);
        if (!init_map_port(set, map, first_port, last_port)) {
                kfree(map);
                return -ENOMEM;
index 69ab9c2634e1566fac04e9509cf4c51e64ea36e8..54f3d7cb23e6efe4a3d9c4084df66cca76a44b03 100644 (file)
@@ -364,25 +364,27 @@ add_extension(enum ip_set_ext_id id, u32 flags, struct nlattr *tb[])
 }
 
 size_t
-ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len)
+ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len,
+               size_t align)
 {
        enum ip_set_ext_id id;
-       size_t offset = len;
        u32 cadt_flags = 0;
 
        if (tb[IPSET_ATTR_CADT_FLAGS])
                cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
        if (cadt_flags & IPSET_FLAG_WITH_FORCEADD)
                set->flags |= IPSET_CREATE_FLAG_FORCEADD;
+       if (!align)
+               align = 1;
        for (id = 0; id < IPSET_EXT_ID_MAX; id++) {
                if (!add_extension(id, cadt_flags, tb))
                        continue;
-               offset = ALIGN(offset, ip_set_extensions[id].align);
-               set->offset[id] = offset;
+               len = ALIGN(len, ip_set_extensions[id].align);
+               set->offset[id] = len;
                set->extensions |= ip_set_extensions[id].type;
-               offset += ip_set_extensions[id].len;
+               len += ip_set_extensions[id].len;
        }
-       return offset;
+       return ALIGN(len, align);
 }
 EXPORT_SYMBOL_GPL(ip_set_elem_len);
 
index 691b54fcaf2a47189665454fdcaff419236b020f..e5336ab36d679d707704a3988baec47360e6b9a4 100644 (file)
@@ -72,8 +72,9 @@ struct hbucket {
        DECLARE_BITMAP(used, AHASH_MAX_TUNED);
        u8 size;                /* size of the array */
        u8 pos;                 /* position of the first free entry */
-       unsigned char value[0]; /* the array of the values */
-} __attribute__ ((aligned));
+       unsigned char value[0]  /* the array of the values */
+               __aligned(__alignof__(u64));
+};
 
 /* The hash table: the table size stored here in order to make resizing easy */
 struct htable {
@@ -475,7 +476,7 @@ static void
 mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
 {
        struct htable *t;
-       struct hbucket *n;
+       struct hbucket *n, *tmp;
        struct mtype_elem *data;
        u32 i, j, d;
 #ifdef IP_SET_HASH_WITH_NETS
@@ -510,9 +511,14 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
                        }
                }
                if (d >= AHASH_INIT_SIZE) {
-                       struct hbucket *tmp = kzalloc(sizeof(*tmp) +
-                                       (n->size - AHASH_INIT_SIZE) * dsize,
-                                       GFP_ATOMIC);
+                       if (d >= n->size) {
+                               rcu_assign_pointer(hbucket(t, i), NULL);
+                               kfree_rcu(n, rcu);
+                               continue;
+                       }
+                       tmp = kzalloc(sizeof(*tmp) +
+                                     (n->size - AHASH_INIT_SIZE) * dsize,
+                                     GFP_ATOMIC);
                        if (!tmp)
                                /* Still try to delete expired elements */
                                continue;
@@ -522,7 +528,7 @@ mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
                                        continue;
                                data = ahash_data(n, j, dsize);
                                memcpy(tmp->value + d * dsize, data, dsize);
-                               set_bit(j, tmp->used);
+                               set_bit(d, tmp->used);
                                d++;
                        }
                        tmp->pos = d;
@@ -1323,12 +1329,14 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
 #endif
                set->variant = &IPSET_TOKEN(HTYPE, 4_variant);
                set->dsize = ip_set_elem_len(set, tb,
-                               sizeof(struct IPSET_TOKEN(HTYPE, 4_elem)));
+                       sizeof(struct IPSET_TOKEN(HTYPE, 4_elem)),
+                       __alignof__(struct IPSET_TOKEN(HTYPE, 4_elem)));
 #ifndef IP_SET_PROTO_UNDEF
        } else {
                set->variant = &IPSET_TOKEN(HTYPE, 6_variant);
                set->dsize = ip_set_elem_len(set, tb,
-                               sizeof(struct IPSET_TOKEN(HTYPE, 6_elem)));
+                       sizeof(struct IPSET_TOKEN(HTYPE, 6_elem)),
+                       __alignof__(struct IPSET_TOKEN(HTYPE, 6_elem)));
        }
 #endif
        if (tb[IPSET_ATTR_TIMEOUT]) {
index 5a30ce6e8c90d278ac37cb0115f45a4390f9a6d7..bbede95c9f68cee1a1e0b5c285231c78d987df63 100644 (file)
@@ -31,7 +31,7 @@ struct set_elem {
        struct rcu_head rcu;
        struct list_head list;
        ip_set_id_t id;
-};
+} __aligned(__alignof__(u64));
 
 struct set_adt_elem {
        ip_set_id_t id;
@@ -618,7 +618,8 @@ list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
                size = IP_SET_LIST_MIN_SIZE;
 
        set->variant = &set_variant;
-       set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem));
+       set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem),
+                                    __alignof__(struct set_elem));
        if (!init_list_set(net, set, size))
                return -ENOMEM;
        if (tb[IPSET_ATTR_TIMEOUT]) {
index 1e24fff53e4b5eef8fab776b2e3dc93a3ae4545c..f57b4dcdb2330e40110ce18ede71b742249edf00 100644 (file)
@@ -1176,6 +1176,7 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
        struct ip_vs_protocol *pp;
        struct ip_vs_proto_data *pd;
        struct ip_vs_conn *cp;
+       struct sock *sk;
 
        EnterFunction(11);
 
@@ -1183,13 +1184,12 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
        if (skb->ipvs_property)
                return NF_ACCEPT;
 
+       sk = skb_to_full_sk(skb);
        /* Bad... Do not break raw sockets */
-       if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
+       if (unlikely(sk && hooknum == NF_INET_LOCAL_OUT &&
                     af == AF_INET)) {
-               struct sock *sk = skb->sk;
-               struct inet_sock *inet = inet_sk(skb->sk);
 
-               if (inet && sk->sk_family == PF_INET && inet->nodefrag)
+               if (sk->sk_family == PF_INET && inet_sk(sk)->nodefrag)
                        return NF_ACCEPT;
        }
 
@@ -1681,6 +1681,7 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
        struct ip_vs_conn *cp;
        int ret, pkts;
        int conn_reuse_mode;
+       struct sock *sk;
 
        /* Already marked as IPVS request or reply? */
        if (skb->ipvs_property)
@@ -1708,12 +1709,11 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
        ip_vs_fill_iph_skb(af, skb, false, &iph);
 
        /* Bad... Do not break raw sockets */
-       if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
+       sk = skb_to_full_sk(skb);
+       if (unlikely(sk && hooknum == NF_INET_LOCAL_OUT &&
                     af == AF_INET)) {
-               struct sock *sk = skb->sk;
-               struct inet_sock *inet = inet_sk(skb->sk);
 
-               if (inet && sk->sk_family == PF_INET && inet->nodefrag)
+               if (sk->sk_family == PF_INET && inet_sk(sk)->nodefrag)
                        return NF_ACCEPT;
        }
 
index 06eb48fceb42e4c31dba2d91c0d182bfc82e5b19..740cce4685acfab8920a46d5d33e40a68da02f8c 100644 (file)
@@ -825,7 +825,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        struct net *net = sock_net(ctnl);
        struct nfnl_log_net *log = nfnl_log_pernet(net);
        int ret = 0;
-       u16 flags;
+       u16 flags = 0;
 
        if (nfula[NFULA_CFG_CMD]) {
                u_int8_t pf = nfmsg->nfgen_family;
index 1067fb4c1ffa2ec24988143fc7ec8d134dc9dda6..c7808fc19719c4687457d039586f9708179b804e 100644 (file)
@@ -47,27 +47,34 @@ static void nft_counter_eval(const struct nft_expr *expr,
        local_bh_enable();
 }
 
-static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)
+static void nft_counter_fetch(const struct nft_counter_percpu __percpu *counter,
+                             struct nft_counter *total)
 {
-       struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
-       struct nft_counter_percpu *cpu_stats;
-       struct nft_counter total;
+       const struct nft_counter_percpu *cpu_stats;
        u64 bytes, packets;
        unsigned int seq;
        int cpu;
 
-       memset(&total, 0, sizeof(total));
+       memset(total, 0, sizeof(*total));
        for_each_possible_cpu(cpu) {
-               cpu_stats = per_cpu_ptr(priv->counter, cpu);
+               cpu_stats = per_cpu_ptr(counter, cpu);
                do {
                        seq     = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
                        bytes   = cpu_stats->counter.bytes;
                        packets = cpu_stats->counter.packets;
                } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
 
-               total.packets += packets;
-               total.bytes += bytes;
+               total->packets += packets;
+               total->bytes += bytes;
        }
+}
+
+static int nft_counter_dump(struct sk_buff *skb, const struct nft_expr *expr)
+{
+       struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
+       struct nft_counter total;
+
+       nft_counter_fetch(priv->counter, &total);
 
        if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes)) ||
            nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.packets)))
@@ -118,6 +125,31 @@ static void nft_counter_destroy(const struct nft_ctx *ctx,
        free_percpu(priv->counter);
 }
 
+static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src)
+{
+       struct nft_counter_percpu_priv *priv = nft_expr_priv(src);
+       struct nft_counter_percpu_priv *priv_clone = nft_expr_priv(dst);
+       struct nft_counter_percpu __percpu *cpu_stats;
+       struct nft_counter_percpu *this_cpu;
+       struct nft_counter total;
+
+       nft_counter_fetch(priv->counter, &total);
+
+       cpu_stats = __netdev_alloc_pcpu_stats(struct nft_counter_percpu,
+                                             GFP_ATOMIC);
+       if (cpu_stats == NULL)
+               return ENOMEM;
+
+       preempt_disable();
+       this_cpu = this_cpu_ptr(cpu_stats);
+       this_cpu->counter.packets = total.packets;
+       this_cpu->counter.bytes = total.bytes;
+       preempt_enable();
+
+       priv_clone->counter = cpu_stats;
+       return 0;
+}
+
 static struct nft_expr_type nft_counter_type;
 static const struct nft_expr_ops nft_counter_ops = {
        .type           = &nft_counter_type,
@@ -126,6 +158,7 @@ static const struct nft_expr_ops nft_counter_ops = {
        .init           = nft_counter_init,
        .destroy        = nft_counter_destroy,
        .dump           = nft_counter_dump,
+       .clone          = nft_counter_clone,
 };
 
 static struct nft_expr_type nft_counter_type __read_mostly = {
index 513a8ef60a5922526eaa7f59fbc5abf1bb0552ba..9dec3bd1b63cc01a784ec025f7cf97f42b38fd06 100644 (file)
@@ -50,8 +50,9 @@ static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr,
        }
 
        ext = nft_set_elem_ext(set, elem);
-       if (priv->expr != NULL)
-               nft_expr_clone(nft_set_ext_expr(ext), priv->expr);
+       if (priv->expr != NULL &&
+           nft_expr_clone(nft_set_ext_expr(ext), priv->expr) < 0)
+               return NULL;
 
        return elem;
 }
index af399cac5205402480300ae7b7d6fbb2094095fb..1cf928fb573e6769a4070327baa74adb300cde7e 100644 (file)
@@ -1741,6 +1741,20 @@ static void fanout_release(struct sock *sk)
                kfree_rcu(po->rollover, rcu);
 }
 
+static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
+                                         struct sk_buff *skb)
+{
+       /* Earlier code assumed this would be a VLAN pkt, double-check
+        * this now that we have the actual packet in hand. We can only
+        * do this check on Ethernet devices.
+        */
+       if (unlikely(dev->type != ARPHRD_ETHER))
+               return false;
+
+       skb_reset_mac_header(skb);
+       return likely(eth_hdr(skb)->h_proto == htons(ETH_P_8021Q));
+}
+
 static const struct proto_ops packet_ops;
 
 static const struct proto_ops packet_ops_spkt;
@@ -1902,18 +1916,10 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
                goto retry;
        }
 
-       if (len > (dev->mtu + dev->hard_header_len + extra_len)) {
-               /* Earlier code assumed this would be a VLAN pkt,
-                * double-check this now that we have the actual
-                * packet in hand.
-                */
-               struct ethhdr *ehdr;
-               skb_reset_mac_header(skb);
-               ehdr = eth_hdr(skb);
-               if (ehdr->h_proto != htons(ETH_P_8021Q)) {
-                       err = -EMSGSIZE;
-                       goto out_unlock;
-               }
+       if (len > (dev->mtu + dev->hard_header_len + extra_len) &&
+           !packet_extra_vlan_len_allowed(dev, skb)) {
+               err = -EMSGSIZE;
+               goto out_unlock;
        }
 
        skb->protocol = proto;
@@ -2332,6 +2338,15 @@ static bool ll_header_truncated(const struct net_device *dev, int len)
        return false;
 }
 
+static void tpacket_set_protocol(const struct net_device *dev,
+                                struct sk_buff *skb)
+{
+       if (dev->type == ARPHRD_ETHER) {
+               skb_reset_mac_header(skb);
+               skb->protocol = eth_hdr(skb)->h_proto;
+       }
+}
+
 static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                void *frame, struct net_device *dev, int size_max,
                __be16 proto, unsigned char *addr, int hlen)
@@ -2368,8 +2383,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        skb_reserve(skb, hlen);
        skb_reset_network_header(skb);
 
-       if (!packet_use_direct_xmit(po))
-               skb_probe_transport_header(skb, 0);
        if (unlikely(po->tp_tx_has_off)) {
                int off_min, off_max, off;
                off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
@@ -2415,6 +2428,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                                dev->hard_header_len);
                if (unlikely(err))
                        return err;
+               if (!skb->protocol)
+                       tpacket_set_protocol(dev, skb);
 
                data += dev->hard_header_len;
                to_write -= dev->hard_header_len;
@@ -2449,6 +2464,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                len = ((to_write > len_max) ? len_max : to_write);
        }
 
+       skb_probe_transport_header(skb, 0);
+
        return tp_len;
 }
 
@@ -2493,12 +2510,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        if (unlikely(!(dev->flags & IFF_UP)))
                goto out_put;
 
-       reserve = dev->hard_header_len + VLAN_HLEN;
+       if (po->sk.sk_socket->type == SOCK_RAW)
+               reserve = dev->hard_header_len;
        size_max = po->tx_ring.frame_size
                - (po->tp_hdrlen - sizeof(struct sockaddr_ll));
 
-       if (size_max > dev->mtu + reserve)
-               size_max = dev->mtu + reserve;
+       if (size_max > dev->mtu + reserve + VLAN_HLEN)
+               size_max = dev->mtu + reserve + VLAN_HLEN;
 
        do {
                ph = packet_current_frame(po, &po->tx_ring,
@@ -2525,18 +2543,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto,
                                          addr, hlen);
                if (likely(tp_len >= 0) &&
-                   tp_len > dev->mtu + dev->hard_header_len) {
-                       struct ethhdr *ehdr;
-                       /* Earlier code assumed this would be a VLAN pkt,
-                        * double-check this now that we have the actual
-                        * packet in hand.
-                        */
+                   tp_len > dev->mtu + reserve &&
+                   !packet_extra_vlan_len_allowed(dev, skb))
+                       tp_len = -EMSGSIZE;
 
-                       skb_reset_mac_header(skb);
-                       ehdr = eth_hdr(skb);
-                       if (ehdr->h_proto != htons(ETH_P_8021Q))
-                               tp_len = -EMSGSIZE;
-               }
                if (unlikely(tp_len < 0)) {
                        if (po->tp_loss) {
                                __packet_set_status(po, ph,
@@ -2765,18 +2775,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 
        sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags);
 
-       if (!gso_type && (len > dev->mtu + reserve + extra_len)) {
-               /* Earlier code assumed this would be a VLAN pkt,
-                * double-check this now that we have the actual
-                * packet in hand.
-                */
-               struct ethhdr *ehdr;
-               skb_reset_mac_header(skb);
-               ehdr = eth_hdr(skb);
-               if (ehdr->h_proto != htons(ETH_P_8021Q)) {
-                       err = -EMSGSIZE;
-                       goto out_free;
-               }
+       if (!gso_type && (len > dev->mtu + reserve + extra_len) &&
+           !packet_extra_vlan_len_allowed(dev, skb)) {
+               err = -EMSGSIZE;
+               goto out_free;
        }
 
        skb->protocol = proto;
@@ -2807,8 +2809,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                len += vnet_hdr_len;
        }
 
-       if (!packet_use_direct_xmit(po))
-               skb_probe_transport_header(skb, reserve);
+       skb_probe_transport_header(skb, reserve);
+
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;
 
@@ -4107,7 +4109,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                err = -EINVAL;
                if (unlikely((int)req->tp_block_size <= 0))
                        goto out;
-               if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
+               if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
                        goto out;
                if (po->tp_version >= TPACKET_V3 &&
                    (int)(req->tp_block_size -
@@ -4119,8 +4121,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
                        goto out;
 
-               rb->frames_per_block = req->tp_block_size/req->tp_frame_size;
-               if (unlikely(rb->frames_per_block <= 0))
+               rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
+               if (unlikely(rb->frames_per_block == 0))
                        goto out;
                if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
                                        req->tp_frame_nr))
index 4f15b7d730e13d6aaa58ba7a28262c9831afea95..1543e39f47c33f6662abd80b5846a845d3760fdc 100644 (file)
@@ -809,8 +809,8 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
        if (!has_sha1)
                return -EINVAL;
 
-       memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0],
-               hmacs->shmac_num_idents * sizeof(__u16));
+       for (i = 0; i < hmacs->shmac_num_idents; i++)
+               ep->auth_hmacs_list->hmac_ids[i] = htons(hmacs->shmac_idents[i]);
        ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) +
                                hmacs->shmac_num_idents * sizeof(__u16));
        return 0;
index 229956bf84577f81d380536b76d1e57d16de53ae..95f82d8d488871e5cc8337acc9073e2aa569b4e6 100644 (file)
@@ -353,12 +353,20 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
 {
        struct rpc_xprt *xprt = req->rq_xprt;
        struct svc_serv *bc_serv = xprt->bc_serv;
+       struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf;
 
        spin_lock(&xprt->bc_pa_lock);
        list_del(&req->rq_bc_pa_list);
        xprt_dec_alloc_count(xprt, 1);
        spin_unlock(&xprt->bc_pa_lock);
 
+       if (copied <= rq_rcv_buf->head[0].iov_len) {
+               rq_rcv_buf->head[0].iov_len = copied;
+               rq_rcv_buf->page_len = 0;
+       } else {
+               rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len;
+       }
+
        req->rq_private_buf.len = copied;
        set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
 
index bc5b7b5032ca54ce95b17de76bb22cbebc8a001a..7fccf9675df8c238e4cc1d1f437540e48a3df9d2 100644 (file)
@@ -1363,6 +1363,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
        memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
        memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
        memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
+       rqstp->rq_arg.len = req->rq_private_buf.len;
 
        /* reset result send buffer "put" position */
        resv->iov_len = 0;
index aaa0b58d6aba29816aa81c0f6ce444a0ab0be0fb..955ec152cb71eac8c91e06f1c922d1df20f6e1f0 100644 (file)
@@ -441,6 +441,7 @@ static void unix_release_sock(struct sock *sk, int embrion)
                if (state == TCP_LISTEN)
                        unix_release_sock(skb->sk, 1);
                /* passed fds are erased in the kfree_skb hook        */
+               UNIXCB(skb).consumed = skb->len;
                kfree_skb(skb);
        }
 
@@ -1799,6 +1800,7 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
                 * this - does no harm
                 */
                consume_skb(newskb);
+               newskb = NULL;
        }
 
        if (skb_append_pagefrags(skb, page, offset, size)) {
@@ -1811,8 +1813,11 @@ static ssize_t unix_stream_sendpage(struct socket *socket, struct page *page,
        skb->truesize += size;
        atomic_add(size, &sk->sk_wmem_alloc);
 
-       if (newskb)
+       if (newskb) {
+               spin_lock(&other->sk_receive_queue.lock);
                __skb_queue_tail(&other->sk_receive_queue, newskb);
+               spin_unlock(&other->sk_receive_queue.lock);
+       }
 
        unix_state_unlock(other);
        mutex_unlock(&unix_sk(other)->readlock);
@@ -2072,6 +2077,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
 
        do {
                int chunk;
+               bool drop_skb;
                struct sk_buff *skb, *last;
 
                unix_state_lock(sk);
@@ -2152,7 +2158,11 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
                }
 
                chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
+               skb_get(skb);
                chunk = state->recv_actor(skb, skip, chunk, state);
+               drop_skb = !unix_skb_len(skb);
+               /* skb is only safe to use if !drop_skb */
+               consume_skb(skb);
                if (chunk < 0) {
                        if (copied == 0)
                                copied = -EFAULT;
@@ -2161,6 +2171,18 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
                copied += chunk;
                size -= chunk;
 
+               if (drop_skb) {
+                       /* the skb was touched by a concurrent reader;
+                        * we should not expect anything from this skb
+                        * anymore and assume it invalid - we can be
+                        * sure it was dropped from the socket queue
+                        *
+                        * let's report a short read
+                        */
+                       err = 0;
+                       break;
+               }
+
                /* Mark read part of skb as used */
                if (!(flags & MSG_PEEK)) {
                        UNIXCB(skb).consumed += chunk;
index 224ebb46bed5f8cf2965103f18ffa659d7629e76..d54f28c6dc5e5450595f1d5472f14cad3c42cee9 100644 (file)
@@ -70,4 +70,10 @@ config SAMPLE_LIVEPATCH
          Builds a sample live patch that replaces the procfs handler
          for /proc/cmdline to print "this has been live patched".
 
+config SAMPLE_CONFIGFS
+       tristate "Build configfs patching sample -- loadable modules only"
+       depends on CONFIGFS_FS && m
+       help
+         Builds a sample configfs interface.
+
 endif # SAMPLES
index f00257bcc5a73570013f5a25253ed8da3e2ee629..48001d7e23f042a7f777ec810ab2ff29e7db5f52 100644 (file)
@@ -1,4 +1,5 @@
 # Makefile for Linux samples code
 
 obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ trace_events/ livepatch/ \
-                          hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/
+                          hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
+                          configfs/
index 79b4596b5f9a45758776d91affe855c59d6fa39d..edd638b5825f8a96e6f6e16fe47f58c4262ca6f1 100644 (file)
@@ -67,10 +67,13 @@ HOSTLOADLIBES_lathist += -lelf
 # point this to your LLVM backend with bpf support
 LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
 
+# asm/sysreg.h inline assmbly used by it is incompatible with llvm.
+# But, ehere is not easy way to fix it, so just exclude it since it is
+# useless for BPF samples.
 $(obj)/%.o: $(src)/%.c
        clang $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \
-               -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
+               -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \
                -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
        clang $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) \
-               -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
+               -D__KERNEL__ -D__ASM_SYSREG_H -Wno-unused-value -Wno-pointer-sign \
                -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf -filetype=asm -o $@.s
diff --git a/samples/configfs/Makefile b/samples/configfs/Makefile
new file mode 100644 (file)
index 0000000..a9afd99
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_SAMPLE_CONFIGFS) += configfs_sample.o
similarity index 74%
rename from Documentation/filesystems/configfs/configfs_example_macros.c
rename to samples/configfs/configfs_sample.c
index 327dfbc640a9087302ce6ea5c6b30c77ad721acf..1ea33119e53272e09ee20e727e44ce21577d6ece 100644 (file)
@@ -54,18 +54,13 @@ struct childless {
 
 static inline struct childless *to_childless(struct config_item *item)
 {
-       return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
+       return item ? container_of(to_configfs_subsystem(to_config_group(item)),
+                       struct childless, subsys) : NULL;
 }
 
-CONFIGFS_ATTR_STRUCT(childless);
-#define CHILDLESS_ATTR(_name, _mode, _show, _store)    \
-struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
-#define CHILDLESS_ATTR_RO(_name, _show)        \
-struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show);
-
-static ssize_t childless_showme_read(struct childless *childless,
-                                    char *page)
+static ssize_t childless_showme_show(struct config_item *item, char *page)
 {
+       struct childless *childless = to_childless(item);
        ssize_t pos;
 
        pos = sprintf(page, "%d\n", childless->showme);
@@ -74,16 +69,15 @@ static ssize_t childless_showme_read(struct childless *childless,
        return pos;
 }
 
-static ssize_t childless_storeme_read(struct childless *childless,
-                                     char *page)
+static ssize_t childless_storeme_show(struct config_item *item, char *page)
 {
-       return sprintf(page, "%d\n", childless->storeme);
+       return sprintf(page, "%d\n", to_childless(item)->storeme);
 }
 
-static ssize_t childless_storeme_write(struct childless *childless,
-                                      const char *page,
-                                      size_t count)
+static ssize_t childless_storeme_store(struct config_item *item,
+               const char *page, size_t count)
 {
+       struct childless *childless = to_childless(item);
        unsigned long tmp;
        char *p = (char *) page;
 
@@ -99,8 +93,7 @@ static ssize_t childless_storeme_write(struct childless *childless,
        return count;
 }
 
-static ssize_t childless_description_read(struct childless *childless,
-                                         char *page)
+static ssize_t childless_description_show(struct config_item *item, char *page)
 {
        return sprintf(page,
 "[01-childless]\n"
@@ -111,26 +104,18 @@ static ssize_t childless_description_read(struct childless *childless,
 "than a directory in /proc.\n");
 }
 
-CHILDLESS_ATTR_RO(showme, childless_showme_read);
-CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
-              childless_storeme_write);
-CHILDLESS_ATTR_RO(description, childless_description_read);
+CONFIGFS_ATTR_RO(childless_, showme);
+CONFIGFS_ATTR(childless_, storeme);
+CONFIGFS_ATTR_RO(childless_, description);
 
 static struct configfs_attribute *childless_attrs[] = {
-       &childless_attr_showme.attr,
-       &childless_attr_storeme.attr,
-       &childless_attr_description.attr,
+       &childless_attr_showme,
+       &childless_attr_storeme,
+       &childless_attr_description,
        NULL,
 };
 
-CONFIGFS_ATTR_OPS(childless);
-static struct configfs_item_operations childless_item_ops = {
-       .show_attribute         = childless_attr_show,
-       .store_attribute        = childless_attr_store,
-};
-
 static struct config_item_type childless_type = {
-       .ct_item_ops    = &childless_item_ops,
        .ct_attrs       = childless_attrs,
        .ct_owner       = THIS_MODULE,
 };
@@ -168,32 +153,13 @@ static inline struct simple_child *to_simple_child(struct config_item *item)
        return item ? container_of(item, struct simple_child, item) : NULL;
 }
 
-static struct configfs_attribute simple_child_attr_storeme = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "storeme",
-       .ca_mode = S_IRUGO | S_IWUSR,
-};
-
-static struct configfs_attribute *simple_child_attrs[] = {
-       &simple_child_attr_storeme,
-       NULL,
-};
-
-static ssize_t simple_child_attr_show(struct config_item *item,
-                                     struct configfs_attribute *attr,
-                                     char *page)
+static ssize_t simple_child_storeme_show(struct config_item *item, char *page)
 {
-       ssize_t count;
-       struct simple_child *simple_child = to_simple_child(item);
-
-       count = sprintf(page, "%d\n", simple_child->storeme);
-
-       return count;
+       return sprintf(page, "%d\n", to_simple_child(item)->storeme);
 }
 
-static ssize_t simple_child_attr_store(struct config_item *item,
-                                      struct configfs_attribute *attr,
-                                      const char *page, size_t count)
+static ssize_t simple_child_storeme_store(struct config_item *item,
+               const char *page, size_t count)
 {
        struct simple_child *simple_child = to_simple_child(item);
        unsigned long tmp;
@@ -211,6 +177,13 @@ static ssize_t simple_child_attr_store(struct config_item *item,
        return count;
 }
 
+CONFIGFS_ATTR(simple_child_, storeme);
+
+static struct configfs_attribute *simple_child_attrs[] = {
+       &simple_child_attr_storeme,
+       NULL,
+};
+
 static void simple_child_release(struct config_item *item)
 {
        kfree(to_simple_child(item));
@@ -218,8 +191,6 @@ static void simple_child_release(struct config_item *item)
 
 static struct configfs_item_operations simple_child_item_ops = {
        .release                = simple_child_release,
-       .show_attribute         = simple_child_attr_show,
-       .store_attribute        = simple_child_attr_store,
 };
 
 static struct config_item_type simple_child_type = {
@@ -235,10 +206,12 @@ struct simple_children {
 
 static inline struct simple_children *to_simple_children(struct config_item *item)
 {
-       return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
+       return item ? container_of(to_config_group(item),
+                       struct simple_children, group) : NULL;
 }
 
-static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
+static struct config_item *simple_children_make_item(struct config_group *group,
+               const char *name)
 {
        struct simple_child *simple_child;
 
@@ -254,20 +227,8 @@ static struct config_item *simple_children_make_item(struct config_group *group,
        return &simple_child->item;
 }
 
-static struct configfs_attribute simple_children_attr_description = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "description",
-       .ca_mode = S_IRUGO,
-};
-
-static struct configfs_attribute *simple_children_attrs[] = {
-       &simple_children_attr_description,
-       NULL,
-};
-
-static ssize_t simple_children_attr_show(struct config_item *item,
-                                        struct configfs_attribute *attr,
-                                        char *page)
+static ssize_t simple_children_description_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page,
 "[02-simple-children]\n"
@@ -276,6 +237,13 @@ static ssize_t simple_children_attr_show(struct config_item *item,
 "items have only one attribute that is readable and writeable.\n");
 }
 
+CONFIGFS_ATTR_RO(simple_children_, description);
+
+static struct configfs_attribute *simple_children_attrs[] = {
+       &simple_children_attr_description,
+       NULL,
+};
+
 static void simple_children_release(struct config_item *item)
 {
        kfree(to_simple_children(item));
@@ -283,7 +251,6 @@ static void simple_children_release(struct config_item *item)
 
 static struct configfs_item_operations simple_children_item_ops = {
        .release        = simple_children_release,
-       .show_attribute = simple_children_attr_show,
 };
 
 /*
@@ -323,7 +290,8 @@ static struct configfs_subsystem simple_children_subsys = {
  * children of its own.
  */
 
-static struct config_group *group_children_make_group(struct config_group *group, const char *name)
+static struct config_group *group_children_make_group(
+               struct config_group *group, const char *name)
 {
        struct simple_children *simple_children;
 
@@ -338,20 +306,8 @@ static struct config_group *group_children_make_group(struct config_group *group
        return &simple_children->group;
 }
 
-static struct configfs_attribute group_children_attr_description = {
-       .ca_owner = THIS_MODULE,
-       .ca_name = "description",
-       .ca_mode = S_IRUGO,
-};
-
-static struct configfs_attribute *group_children_attrs[] = {
-       &group_children_attr_description,
-       NULL,
-};
-
-static ssize_t group_children_attr_show(struct config_item *item,
-                                       struct configfs_attribute *attr,
-                                       char *page)
+static ssize_t group_children_description_show(struct config_item *item,
+               char *page)
 {
        return sprintf(page,
 "[03-group-children]\n"
@@ -360,8 +316,11 @@ static ssize_t group_children_attr_show(struct config_item *item,
 "groups are like the subsystem simple-children.\n");
 }
 
-static struct configfs_item_operations group_children_item_ops = {
-       .show_attribute = group_children_attr_show,
+CONFIGFS_ATTR_RO(group_children_, description);
+
+static struct configfs_attribute *group_children_attrs[] = {
+       &group_children_attr_description,
+       NULL,
 };
 
 /*
@@ -373,7 +332,6 @@ static struct configfs_group_operations group_children_group_ops = {
 };
 
 static struct config_item_type group_children_type = {
-       .ct_item_ops    = &group_children_item_ops,
        .ct_group_ops   = &group_children_group_ops,
        .ct_attrs       = group_children_attrs,
        .ct_owner       = THIS_MODULE,
index 125b906cd1d4bba50c727b108ead1a3d81e1e302..638a38e1b419518712c1f44c1497e80bac096240 100755 (executable)
@@ -2711,7 +2711,7 @@ $kernelversion = get_kernel_version();
 
 # generate a sequence of code that will splice in highlighting information
 # using the s// operator.
-foreach my $k (keys @highlights) {
+for (my $k = 0; $k < @highlights; $k++) {
     my $pattern = $highlights[$k][0];
     my $result = $highlights[$k][1];
 #   print STDERR "scanning pattern:$pattern, highlight:($result)\n";
index 927db9f35ad6f1bddeb51169e84c1bb526f85f21..696ccfa08d103cd29ae56ac38c117bbd7725da06 100644 (file)
@@ -845,6 +845,8 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
        size_t datalen = prep->datalen;
        int ret = 0;
 
+       if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+               return -ENOKEY;
        if (datalen <= 0 || datalen > 32767 || !prep->data)
                return -EINVAL;
 
index 903dace648a1731b2afbb2dc8b40b8169a05aba2..16dec53184b663f745c010d11e78128ca995bf58 100644 (file)
@@ -1007,13 +1007,16 @@ static void trusted_rcu_free(struct rcu_head *rcu)
  */
 static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 {
-       struct trusted_key_payload *p = key->payload.data[0];
+       struct trusted_key_payload *p;
        struct trusted_key_payload *new_p;
        struct trusted_key_options *new_o;
        size_t datalen = prep->datalen;
        char *datablob;
        int ret = 0;
 
+       if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+               return -ENOKEY;
+       p = key->payload.data[0];
        if (!p->migratable)
                return -EPERM;
        if (datalen <= 0 || datalen > 32767 || !prep->data)
index 28cb30f80256911cf9ee41631659b9e8f5a6b5dd..8705d79b2c6f289736fde21fd38e6013a4e4ae3c 100644 (file)
@@ -120,7 +120,10 @@ int user_update(struct key *key, struct key_preparsed_payload *prep)
 
        if (ret == 0) {
                /* attach the new data, displacing the old */
-               zap = key->payload.data[0];
+               if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
+                       zap = key->payload.data[0];
+               else
+                       zap = NULL;
                rcu_assign_keypointer(key, upayload);
                key->expiry = 0;
        }
index 18643bf9894d5e393bdb51b0d7b0740f34960e75..456e1a9bcfde14e594789de0b1055c63f8dd549e 100644 (file)
@@ -638,7 +638,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
 {
        struct avtab_node *node;
 
-       if (!ctab || !key || !avd || !xperms)
+       if (!ctab || !key || !avd)
                return;
 
        for (node = avtab_search_node(ctab, key); node;
@@ -657,7 +657,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
                if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
                    (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
                        avd->auditallow |= node->datum.u.data;
-               if ((node->key.specified & AVTAB_ENABLED) &&
+               if (xperms && (node->key.specified & AVTAB_ENABLED) &&
                                (node->key.specified & AVTAB_XPERMS))
                        services_compute_xperms_drivers(xperms, node);
        }
index bee0e5f1a1166d18e443f8294754f01bf55101ca..e92a6d949847a3fbc3de4ad7edc2ecd6026fbae3 100644 (file)
@@ -38,6 +38,7 @@ config SND_OXFW
           * Mackie(Loud) Tapco Link.Firewire
           * Mackie(Loud) d.2 pro/d.4 pro
           * Mackie(Loud) U.420/U.420d
+          * TASCAM FireOne
 
          To compile this driver as a module, choose M here: the module
          will be called snd-oxfw.
index 5d99436dfcaee5e70f3957a8f8b59be3d9e213d3..0cda05c72f504383a5031e06aa956e2544ef93c8 100644 (file)
@@ -12,9 +12,11 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_LICENSE("GPL v2");
 
 #define OUI_WEISS              0x001c6a
+#define OUI_LOUD               0x000ff2
 
 #define DICE_CATEGORY_ID       0x04
 #define WEISS_CATEGORY_ID      0x00
+#define LOUD_CATEGORY_ID       0x10
 
 static int dice_interface_check(struct fw_unit *unit)
 {
@@ -57,6 +59,8 @@ static int dice_interface_check(struct fw_unit *unit)
        }
        if (vendor == OUI_WEISS)
                category = WEISS_CATEGORY_ID;
+       else if (vendor == OUI_LOUD)
+               category = LOUD_CATEGORY_ID;
        else
                category = DICE_CATEGORY_ID;
        if (device->config_rom[3] != ((vendor << 8) | category) ||
index edfc1b8d553ee3c6e1ad4bfd4d424fce7631b292..656ce39bddbc531c27d5a15b6d07e899e17f1cd6 100644 (file)
@@ -25,7 +25,7 @@ config SND_ALS300
        select SND_PCM
        select SND_AC97_CODEC
        select SND_OPL3_LIB
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
 
@@ -50,7 +50,7 @@ config SND_ALI5451
        tristate "ALi M5451 PCI Audio Controller"
        select SND_MPU401_UART
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for the integrated AC97 sound
          device on motherboards using the ALi M5451 Audio Controller
@@ -155,7 +155,7 @@ config SND_AZT3328
        select SND_PCM
        select SND_RAWMIDI
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for Aztech AZF3328 (PCI168)
          soundcards.
@@ -463,7 +463,7 @@ config SND_EMU10K1
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y to include support for Sound Blaster PCI 512, Live!,
          Audigy and E-mu APS (partially supported) soundcards.
@@ -479,7 +479,7 @@ config SND_EMU10K1X
        tristate "Emu10k1X (Dell OEM Version)"
        select SND_AC97_CODEC
        select SND_RAWMIDI
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for the Dell OEM version of the
          Sound Blaster Live!.
@@ -513,7 +513,7 @@ config SND_ES1938
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Solo-1
          (ES1938, ES1946, ES1969) chips.
@@ -525,7 +525,7 @@ config SND_ES1968
        tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
        select SND_MPU401_UART
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Maestro
          1/2/2E chips.
@@ -612,7 +612,7 @@ config SND_ICE1712
        select SND_MPU401_UART
        select SND_AC97_CODEC
        select BITREVERSE
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on the
          ICE1712 (Envy24) chip.
@@ -700,7 +700,7 @@ config SND_LX6464ES
 config SND_MAESTRO3
        tristate "ESS Allegro/Maestro3"
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on ESS Maestro 3
          (Allegro) chips.
@@ -806,7 +806,7 @@ config SND_SIS7019
        tristate "SiS 7019 Audio Accelerator"
        depends on X86_32
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for the SiS 7019 Audio Accelerator.
 
@@ -818,7 +818,7 @@ config SND_SONICVIBES
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on the S3
          SonicVibes chip.
@@ -830,7 +830,7 @@ config SND_TRIDENT
        tristate "Trident 4D-Wave DX/NX; SiS 7018"
        select SND_MPU401_UART
        select SND_AC97_CODEC
-       select ZONE_DMA
+       depends on ZONE_DMA
        help
          Say Y here to include support for soundcards based on Trident
          4D-Wave DX/NX or SiS 7018 chips.
index c7dc38d41b7f4678691e5a492b93b5087bddddce..5fcbb065d8702bd051b3a69789bcfe5b3b5d4da2 100644 (file)
@@ -49,7 +49,7 @@ static int amixer_output_slot(const struct rsc *rsc)
        return (amixer_index(rsc) << 4) + 0x4;
 }
 
-static struct rsc_ops amixer_basic_rsc_ops = {
+static const struct rsc_ops amixer_basic_rsc_ops = {
        .master         = amixer_master,
        .next_conj      = amixer_next_conj,
        .index          = amixer_index,
@@ -186,7 +186,7 @@ static int amixer_setup(struct amixer *amixer, struct rsc *input,
        return 0;
 }
 
-static struct amixer_rsc_ops amixer_ops = {
+static const struct amixer_rsc_ops amixer_ops = {
        .set_input              = amixer_set_input,
        .set_invalid_squash     = amixer_set_invalid_squash,
        .set_scale              = amixer_set_y,
@@ -357,7 +357,7 @@ static int sum_output_slot(const struct rsc *rsc)
        return (sum_index(rsc) << 4) + 0xc;
 }
 
-static struct rsc_ops sum_basic_rsc_ops = {
+static const struct rsc_ops sum_basic_rsc_ops = {
        .master         = sum_master,
        .next_conj      = sum_next_conj,
        .index          = sum_index,
index 72f42f27434eb7f4dcada14fe737be047d03d7f0..2de18aa6508dbd4b9a363e2f760c2fdb4cd6bf63 100644 (file)
@@ -58,7 +58,7 @@ struct amixer {
        unsigned char idx[8];
        struct rsc *input;      /* pointer to a resource acting as source */
        struct sum *sum;        /* Put amixer output to this summation node */
-       struct amixer_rsc_ops *ops;     /* AMixer specific operations */
+       const struct amixer_rsc_ops *ops;       /* AMixer specific operations */
 };
 
 struct amixer_rsc_ops {
index 9b87dd28de8349f38adf4cfc572019abe82cd156..7f089cb433e17d6c9dde341d09b328aa471ec0c1 100644 (file)
@@ -83,21 +83,21 @@ static int daio_in_next_conj_20k2(struct rsc *rsc)
        return rsc->conj += 0x100;
 }
 
-static struct rsc_ops daio_out_rsc_ops = {
+static const struct rsc_ops daio_out_rsc_ops = {
        .master         = daio_master,
        .next_conj      = daio_out_next_conj,
        .index          = daio_index,
        .output_slot    = NULL,
 };
 
-static struct rsc_ops daio_in_rsc_ops_20k1 = {
+static const struct rsc_ops daio_in_rsc_ops_20k1 = {
        .master         = daio_master,
        .next_conj      = daio_in_next_conj_20k1,
        .index          = NULL,
        .output_slot    = daio_index,
 };
 
-static struct rsc_ops daio_in_rsc_ops_20k2 = {
+static const struct rsc_ops daio_in_rsc_ops_20k2 = {
        .master         = daio_master,
        .next_conj      = daio_in_next_conj_20k2,
        .index          = NULL,
@@ -263,7 +263,7 @@ static int dao_clear_right_input(struct dao *dao)
        return 0;
 }
 
-static struct dao_rsc_ops dao_ops = {
+static const struct dao_rsc_ops dao_ops = {
        .set_spos               = dao_spdif_set_spos,
        .commit_write           = dao_commit_write,
        .get_spos               = dao_spdif_get_spos,
@@ -318,7 +318,7 @@ static int dai_commit_write(struct dai *dai)
        return 0;
 }
 
-static struct dai_rsc_ops dai_ops = {
+static const struct dai_rsc_ops dai_ops = {
        .set_srt_srcl           = dai_set_srt_srcl,
        .set_srt_srcr           = dai_set_srt_srcr,
        .set_srt_msr            = dai_set_srt_msr,
index 0ebbf350f51aa8a6b3a64e91aa3a278e0b44ebf0..a30be73b08ea6c4bb50cb5735d6fa7d0978d0a9d 100644 (file)
@@ -51,7 +51,7 @@ struct daio {
 
 struct dao {
        struct daio daio;
-       struct dao_rsc_ops *ops;        /* DAO specific operations */
+       const struct dao_rsc_ops *ops;  /* DAO specific operations */
        struct imapper **imappers;
        struct daio_mgr *mgr;
        struct hw *hw;
@@ -60,7 +60,7 @@ struct dao {
 
 struct dai {
        struct daio daio;
-       struct dai_rsc_ops *ops;        /* DAI specific operations */
+       const struct dai_rsc_ops *ops;  /* DAI specific operations */
        struct hw *hw;
        void *ctrl_blk;
 };
index 1a97e406d8ec00aaa36b430a8d8d02419cb30fca..c5124c3c0fd192bb8d25528f779b7755d748d057 100644 (file)
@@ -127,7 +127,7 @@ static int rsc_master(struct rsc *rsc)
        return rsc->conj = rsc->idx;
 }
 
-static struct rsc_ops rsc_generic_ops = {
+static const struct rsc_ops rsc_generic_ops = {
        .index          = rsc_index,
        .output_slot    = audio_ring_slot,
        .master         = rsc_master,
index 9b746c3719e6219faa30b116b762675376867631..736d9f7e9e165844fe75419a5e063ad02565814b 100644 (file)
@@ -39,7 +39,7 @@ struct rsc {
        u32 msr:4;      /* The Master Sample Rate a resource working on */
        void *ctrl_blk; /* Chip specific control info block for a resource */
        struct hw *hw;  /* Chip specific object for hardware access means */
-       struct rsc_ops *ops;    /* Generic resource operations */
+       const struct rsc_ops *ops;      /* Generic resource operations */
 };
 
 struct rsc_ops {
index ec1f08464d938ce0adc3660f3ae8efbb799d7cde..a5a72df298013faae602f1cdcb95a7b4cda3d865 100644 (file)
@@ -335,7 +335,7 @@ static int src_default_config_arcrw(struct src *src)
        return 0;
 }
 
-static struct src_rsc_ops src_rsc_ops = {
+static const struct src_rsc_ops src_rsc_ops = {
        .set_state              = src_set_state,
        .set_bm                 = src_set_bm,
        .set_sf                 = src_set_sf,
@@ -611,7 +611,7 @@ static int srcimp_index(const struct rsc *rsc)
        return container_of(rsc, struct srcimp, rsc)->idx[rsc->conj];
 }
 
-static struct rsc_ops srcimp_basic_rsc_ops = {
+static const struct rsc_ops srcimp_basic_rsc_ops = {
        .master         = srcimp_master,
        .next_conj      = srcimp_next_conj,
        .index          = srcimp_index,
@@ -662,7 +662,7 @@ static int srcimp_unmap(struct srcimp *srcimp)
        return 0;
 }
 
-static struct srcimp_rsc_ops srcimp_ops = {
+static const struct srcimp_rsc_ops srcimp_ops = {
        .map = srcimp_map,
        .unmap = srcimp_unmap
 };
index da7573c5db9bb6bdfd974c03c758a33c32170e65..92944a012bc4b6dc8bc4d2a6a448bbc2933947c0 100644 (file)
@@ -48,7 +48,7 @@ struct src_rsc_ops;
 struct src {
        struct rsc rsc; /* Basic resource info */
        struct src *intlv; /* Pointer to next interleaved SRC in a series */
-       struct src_rsc_ops *ops; /* SRC specific operations */
+       const struct src_rsc_ops *ops; /* SRC specific operations */
        /* Number of contiguous srcs for interleaved usage */
        unsigned char multi;
        unsigned char mode; /* Working mode of this SRC resource */
@@ -110,7 +110,7 @@ struct srcimp {
        struct imapper *imappers;
        unsigned int mapped; /* A bit-map indicating which conj rsc is mapped */
        struct srcimp_mgr *mgr;
-       struct srcimp_rsc_ops *ops;
+       const struct srcimp_rsc_ops *ops;
 };
 
 struct srcimp_rsc_ops {
index 8a7fbdcb4072f6a35f956ba51a5820f3d3054eaf..963f82430938a976826074bfe41f33f286e3fbe1 100644 (file)
@@ -312,6 +312,10 @@ enum {
        (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\
         AZX_DCAPS_I915_POWERWELL)
 
+#define AZX_DCAPS_INTEL_BROXTON \
+       (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\
+        AZX_DCAPS_I915_POWERWELL)
+
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
        (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB |\
@@ -2124,6 +2128,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Sunrise Point-LP */
        { PCI_DEVICE(0x8086, 0x9d70),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Broxton-P(Apollolake) */
+       { PCI_DEVICE(0x8086, 0x5a98),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0a0c),
          .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
index 366efbf87d41c7d5a3e3826bbb74d25fcf09e5fd..c945e257d368890bcd3f72037568e566c0ba9221 100644 (file)
@@ -383,7 +383,7 @@ static void hda_free_jack_priv(struct snd_jack *jack)
  * This assigns a jack-detection kctl to the given pin.  The kcontrol
  * will have the given name and index.
  */
-static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
+int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
                          const char *name, bool phantom_jack)
 {
        struct hda_jack_tbl *jack;
@@ -410,20 +410,6 @@ static int __snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 
        return 0;
 }
-
-/**
- * snd_hda_jack_add_kctl - Add a jack kctl for the given pin
- * @codec: the HDA codec
- * @nid: pin NID
- * @name: the name string for the jack ctl
- *
- * This is a simple helper calling __snd_hda_jack_add_kctl().
- */
-int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
-                         const char *name)
-{
-       return __snd_hda_jack_add_kctl(codec, nid, name, false);
-}
 EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl);
 
 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
@@ -451,7 +437,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
        if (phantom_jack)
                /* Example final name: "Internal Mic Phantom Jack" */
                strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
-       err = __snd_hda_jack_add_kctl(codec, nid, name, phantom_jack);
+       err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack);
        if (err < 0)
                return err;
 
index 387d30984dfe3dd496e6a247ef34c221dce12981..858708a044f57ef563d79a100c5a92e5f3adaa3d 100644 (file)
@@ -82,7 +82,7 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
 bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
 
 int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
-                         const char *name);
+                         const char *name, bool phantom_jack);
 int snd_hda_jack_add_kctls(struct hda_codec *codec,
                           const struct auto_pin_cfg *cfg);
 
index f503a883bef31d0fd55a38dd816f70609edcaf82..bdb6f226d00686f67e29cbcf29f6259df0431145 100644 (file)
@@ -50,8 +50,9 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 #define is_haswell(codec)  ((codec)->core.vendor_id == 0x80862807)
 #define is_broadwell(codec)    ((codec)->core.vendor_id == 0x80862808)
 #define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809)
+#define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a)
 #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
-                                       || is_skylake(codec))
+                               || is_skylake(codec) || is_broxton(codec))
 
 #define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
 #define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
@@ -2096,14 +2097,17 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
        struct hdmi_spec *spec = codec->spec;
        struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
        int pcmdev = get_pcm_rec(spec, pin_idx)->device;
+       bool phantom_jack;
 
        if (pcmdev > 0)
                sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
-       if (!is_jack_detectable(codec, per_pin->pin_nid))
+       phantom_jack = !is_jack_detectable(codec, per_pin->pin_nid);
+       if (phantom_jack)
                strncat(hdmi_str, " Phantom",
                        sizeof(hdmi_str) - strlen(hdmi_str) - 1);
 
-       return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str);
+       return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str,
+                                    phantom_jack);
 }
 
 static int generic_hdmi_build_controls(struct hda_codec *codec)
@@ -2374,7 +2378,8 @@ static int patch_generic_hdmi(struct hda_codec *codec)
         * can cover the codec power request, and so need not set this flag.
         * For previous platforms, there is no such power well feature.
         */
-       if (is_valleyview_plus(codec) || is_skylake(codec))
+       if (is_valleyview_plus(codec) || is_skylake(codec) ||
+                       is_broxton(codec))
                codec->core.link_power_control = 1;
 
        if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
index 2f7b065f9ac43e88ee19b6845506c066485c679a..9bedf7c85e295d6dab65c04093abf7a58cab1a5a 100644 (file)
@@ -1759,6 +1759,7 @@ enum {
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
        ALC887_FIXUP_BASS_CHMAP,
+       ALC882_FIXUP_DISABLE_AAMIX,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -1920,6 +1921,8 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
 
 static void alc_fixup_bass_chmap(struct hda_codec *codec,
                                 const struct hda_fixup *fix, int action);
+static void alc_fixup_disable_aamix(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action);
 
 static const struct hda_fixup alc882_fixups[] = {
        [ALC882_FIXUP_ABIT_AW9D_MAX] = {
@@ -2151,6 +2154,10 @@ static const struct hda_fixup alc882_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_bass_chmap,
        },
+       [ALC882_FIXUP_DISABLE_AAMIX] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2218,6 +2225,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -4587,6 +4595,7 @@ enum {
        ALC292_FIXUP_DISABLE_AAMIX,
        ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC275_FIXUP_DELL_XPS,
+       ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5167,6 +5176,17 @@ static const struct hda_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Disable pass-through path for FRONT 14h */
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x36},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0x1737},
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5180,8 +5200,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
+       SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
+       SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
        SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X),
        SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X),
        SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
@@ -5204,6 +5226,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
        SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
+       SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
index 826122d8aceec4a931e64e99875dcd8cef661736..2c7c5eb8b1e9514779b78bc278412803862062e9 100644 (file)
@@ -3110,6 +3110,29 @@ static void stac92hd71bxx_fixup_hp_hdx(struct hda_codec *codec,
        spec->gpio_led = 0x08;
 }
 
+static bool is_hp_output(struct hda_codec *codec, hda_nid_t pin)
+{
+       unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, pin);
+
+       /* count line-out, too, as BIOS sets often so */
+       return get_defcfg_connect(pin_cfg) != AC_JACK_PORT_NONE &&
+               (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT ||
+                get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT);
+}
+
+static void fixup_hp_headphone(struct hda_codec *codec, hda_nid_t pin)
+{
+       unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, pin);
+
+       /* It was changed in the BIOS to just satisfy MS DTM.
+        * Lets turn it back into slaved HP
+        */
+       pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) |
+               (AC_JACK_HP_OUT << AC_DEFCFG_DEVICE_SHIFT);
+       pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC | AC_DEFCFG_SEQUENCE))) |
+               0x1f;
+       snd_hda_codec_set_pincfg(codec, pin, pin_cfg);
+}
 
 static void stac92hd71bxx_fixup_hp(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
@@ -3119,22 +3142,12 @@ static void stac92hd71bxx_fixup_hp(struct hda_codec *codec,
        if (action != HDA_FIXUP_ACT_PRE_PROBE)
                return;
 
-       if (hp_blike_system(codec->core.subsystem_id)) {
-               unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f);
-               if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT ||
-                       get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER  ||
-                       get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT) {
-                       /* It was changed in the BIOS to just satisfy MS DTM.
-                        * Lets turn it back into slaved HP
-                        */
-                       pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE))
-                                       | (AC_JACK_HP_OUT <<
-                                               AC_DEFCFG_DEVICE_SHIFT);
-                       pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC
-                                                       | AC_DEFCFG_SEQUENCE)))
-                                                               | 0x1f;
-                       snd_hda_codec_set_pincfg(codec, 0x0f, pin_cfg);
-               }
+       /* when both output A and F are assigned, these are supposedly
+        * dock and built-in headphones; fix both pin configs
+        */
+       if (is_hp_output(codec, 0x0a) && is_hp_output(codec, 0x0f)) {
+               fixup_hp_headphone(codec, 0x0a);
+               fixup_hp_headphone(codec, 0x0f);
        }
 
        if (find_mute_led_cfg(codec, 1))
index 11e953a1fa45a06ab9243eca4d99d5b3f16ea9ef..99b73c675743661318ac5cf4bd3000e26e3627a7 100644 (file)
@@ -655,7 +655,7 @@ static void cleanup_oss_soundcore(void)
 static int __init init_oss_soundcore(void)
 {
        if (preclaim_oss &&
-           register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) {
+           register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) < 0) {
                printk(KERN_ERR "soundcore: sound device already in use.\n");
                return -EBUSY;
        }
index 7661616f36361d142144842bd6595994829edec4..5b4c58c3e2c5f6115d55ad194cd06f971e3fdb70 100644 (file)
@@ -174,6 +174,8 @@ struct snd_usb_midi_in_endpoint {
                u8 running_status_length;
        } ports[0x10];
        u8 seen_f5;
+       bool in_sysex;
+       u8 last_cin;
        u8 error_resubmit;
        int current_port;
 };
@@ -467,6 +469,39 @@ static void snd_usbmidi_maudio_broken_running_status_input(
                }
 }
 
+/*
+ * QinHeng CH345 is buggy: every second packet inside a SysEx has not CIN 4
+ * but the previously seen CIN, but still with three data bytes.
+ */
+static void ch345_broken_sysex_input(struct snd_usb_midi_in_endpoint *ep,
+                                    uint8_t *buffer, int buffer_length)
+{
+       unsigned int i, cin, length;
+
+       for (i = 0; i + 3 < buffer_length; i += 4) {
+               if (buffer[i] == 0 && i > 0)
+                       break;
+               cin = buffer[i] & 0x0f;
+               if (ep->in_sysex &&
+                   cin == ep->last_cin &&
+                   (buffer[i + 1 + (cin == 0x6)] & 0x80) == 0)
+                       cin = 0x4;
+#if 0
+               if (buffer[i + 1] == 0x90) {
+                       /*
+                        * Either a corrupted running status or a real note-on
+                        * message; impossible to detect reliably.
+                        */
+               }
+#endif
+               length = snd_usbmidi_cin_length[cin];
+               snd_usbmidi_input_data(ep, 0, &buffer[i + 1], length);
+               ep->in_sysex = cin == 0x4;
+               if (!ep->in_sysex)
+                       ep->last_cin = cin;
+       }
+}
+
 /*
  * CME protocol: like the standard protocol, but SysEx commands are sent as a
  * single USB packet preceded by a 0x0F byte.
@@ -660,6 +695,12 @@ static struct usb_protocol_ops snd_usbmidi_cme_ops = {
        .output_packet = snd_usbmidi_output_standard_packet,
 };
 
+static struct usb_protocol_ops snd_usbmidi_ch345_broken_sysex_ops = {
+       .input = ch345_broken_sysex_input,
+       .output = snd_usbmidi_standard_output,
+       .output_packet = snd_usbmidi_output_standard_packet,
+};
+
 /*
  * AKAI MPD16 protocol:
  *
@@ -1341,6 +1382,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
                 * Various chips declare a packet size larger than 4 bytes, but
                 * do not actually work with larger packets:
                 */
+       case USB_ID(0x0a67, 0x5011): /* Medeli DD305 */
        case USB_ID(0x0a92, 0x1020): /* ESI M4U */
        case USB_ID(0x1430, 0x474b): /* RedOctane GH MIDI INTERFACE */
        case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */
@@ -2376,6 +2418,10 @@ int snd_usbmidi_create(struct snd_card *card,
                if (err < 0)
                        break;
 
+               err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+               break;
+       case QUIRK_MIDI_CH345:
+               umidi->usb_protocol_ops = &snd_usbmidi_ch345_broken_sysex_ops;
                err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
                break;
        default:
index 1a1e2e4df35e5809e7f7d81b405ca6dddf2f4311..c60a776e815d72f14b9b6345f2e8a0266f8ec1b6 100644 (file)
@@ -2829,6 +2829,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        .idProduct = 0x1020,
 },
 
+/* QinHeng devices */
+{
+       USB_DEVICE(0x1a86, 0x752d),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "QinHeng",
+               .product_name = "CH345",
+               .ifnum = 1,
+               .type = QUIRK_MIDI_CH345
+       }
+},
+
 /* KeithMcMillen Stringport */
 {
        USB_DEVICE(0x1f38, 0x0001),
index 4897ea171194f474c352c45579f62aa036d219ea..7016ad8981873ca046000d631ac112c12ed62dc1 100644 (file)
@@ -538,6 +538,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
                [QUIRK_MIDI_AKAI] = create_any_midi_quirk,
                [QUIRK_MIDI_FTDI] = create_any_midi_quirk,
+               [QUIRK_MIDI_CH345] = create_any_midi_quirk,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
@@ -1274,6 +1275,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */
        case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
        case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
+       case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
                if (fp->altsetting == 3)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
index 15a12715bd05154bd9c0b4bbe7084f3df15022b2..b665d85555cb3aad0c9a621232f28d8e1f75344a 100644 (file)
@@ -95,6 +95,7 @@ enum quirk_type {
        QUIRK_MIDI_AKAI,
        QUIRK_MIDI_US122L,
        QUIRK_MIDI_FTDI,
+       QUIRK_MIDI_CH345,
        QUIRK_AUDIO_STANDARD_INTERFACE,
        QUIRK_AUDIO_FIXED_ENDPOINT,
        QUIRK_AUDIO_EDIROL_UAXX,
index d6f307dfb1a3c090dc94472f9761c377616ebb92..7dc820a8c1f11b0973605aab313e2ecaa75ca1a6 100644 (file)
@@ -32,6 +32,10 @@ help:
        @echo '  from the kernel command line to build and install one of'
        @echo '  the tools above'
        @echo ''
+       @echo '  $$ make tools/all'
+       @echo ''
+       @echo '  builds all tools.'
+       @echo ''
        @echo '  $$ make tools/install'
        @echo ''
        @echo '  installs all tools.'
@@ -77,6 +81,11 @@ tmon: FORCE
 freefall: FORCE
        $(call descend,laptop/$@)
 
+all: acpi cgroup cpupower hv firewire lguest \
+               perf selftests turbostat usb \
+               virtio vm net x86_energy_perf_policy \
+               tmon freefall
+
 acpi_install:
        $(call descend,power/$(@:_install=),install)
 
@@ -101,7 +110,7 @@ freefall_install:
 install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
                perf_install selftests_install turbostat_install usb_install \
                virtio_install vm_install net_install x86_energy_perf_policy_install \
-               tmon freefall_install
+               tmon_install freefall_install
 
 acpi_clean:
        $(call descend,power/acpi,clean)
index 76b014c968935aa028f2bc6cb78bfdfbd2a1def7..a017f1595676d32b5cd28ed4f6ab75b9d2278934 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
index 812aeedaea387d23197061bc20bd2abeeb281c7e..f81e549ddfdb18e6e3c86d063bb131cfcbadb810 100644 (file)
@@ -1,2 +1,2 @@
 libbpf_version.h
-FEATURE-DUMP
+FEATURE-DUMP.libbpf
index fc9af57b666e244b6b1c06cd163738068190b6f8..a3caaf3eafbdbc6c7afda606cbf35b6888324ef4 100644 (file)
@@ -180,7 +180,7 @@ config-clean:
 clean:
        $(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
                $(RM) LIBBPF-CFLAGS
-       $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP
+       $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
 
 
 
index 4252fc22f78f4f8fd4c204975b5464f5bbc192e0..e176bad19bcb73689665ea9bd083075dff0e73fa 100644 (file)
@@ -61,6 +61,60 @@ void libbpf_set_print(libbpf_print_fn_t warn,
        __pr_debug = debug;
 }
 
+#define STRERR_BUFSIZE  128
+
+#define ERRNO_OFFSET(e)                ((e) - __LIBBPF_ERRNO__START)
+#define ERRCODE_OFFSET(c)      ERRNO_OFFSET(LIBBPF_ERRNO__##c)
+#define NR_ERRNO       (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START)
+
+static const char *libbpf_strerror_table[NR_ERRNO] = {
+       [ERRCODE_OFFSET(LIBELF)]        = "Something wrong in libelf",
+       [ERRCODE_OFFSET(FORMAT)]        = "BPF object format invalid",
+       [ERRCODE_OFFSET(KVERSION)]      = "'version' section incorrect or lost",
+       [ERRCODE_OFFSET(ENDIAN)]        = "Endian missmatch",
+       [ERRCODE_OFFSET(INTERNAL)]      = "Internal error in libbpf",
+       [ERRCODE_OFFSET(RELOC)]         = "Relocation failed",
+       [ERRCODE_OFFSET(VERIFY)]        = "Kernel verifier blocks program loading",
+       [ERRCODE_OFFSET(PROG2BIG)]      = "Program too big",
+       [ERRCODE_OFFSET(KVER)]          = "Incorrect kernel version",
+};
+
+int libbpf_strerror(int err, char *buf, size_t size)
+{
+       if (!buf || !size)
+               return -1;
+
+       err = err > 0 ? err : -err;
+
+       if (err < __LIBBPF_ERRNO__START) {
+               int ret;
+
+               ret = strerror_r(err, buf, size);
+               buf[size - 1] = '\0';
+               return ret;
+       }
+
+       if (err < __LIBBPF_ERRNO__END) {
+               const char *msg;
+
+               msg = libbpf_strerror_table[ERRNO_OFFSET(err)];
+               snprintf(buf, size, "%s", msg);
+               buf[size - 1] = '\0';
+               return 0;
+       }
+
+       snprintf(buf, size, "Unknown libbpf error %d", err);
+       buf[size - 1] = '\0';
+       return -1;
+}
+
+#define CHECK_ERR(action, err, out) do {       \
+       err = action;                   \
+       if (err)                        \
+               goto out;               \
+} while(0)
+
+
 /* Copied from tools/perf/util/util.h */
 #ifndef zfree
 # define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
@@ -258,7 +312,7 @@ static struct bpf_object *bpf_object__new(const char *path,
        obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
        if (!obj) {
                pr_warning("alloc memory failed for %s\n", path);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        strcpy(obj->path, path);
@@ -305,7 +359,7 @@ static int bpf_object__elf_init(struct bpf_object *obj)
 
        if (obj_elf_valid(obj)) {
                pr_warning("elf init: internal error\n");
-               return -EEXIST;
+               return -LIBBPF_ERRNO__LIBELF;
        }
 
        if (obj->efile.obj_buf_sz > 0) {
@@ -331,14 +385,14 @@ static int bpf_object__elf_init(struct bpf_object *obj)
        if (!obj->efile.elf) {
                pr_warning("failed to open %s as ELF file\n",
                                obj->path);
-               err = -EINVAL;
+               err = -LIBBPF_ERRNO__LIBELF;
                goto errout;
        }
 
        if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
                pr_warning("failed to get EHDR from %s\n",
                                obj->path);
-               err = -EINVAL;
+               err = -LIBBPF_ERRNO__FORMAT;
                goto errout;
        }
        ep = &obj->efile.ehdr;
@@ -346,7 +400,7 @@ static int bpf_object__elf_init(struct bpf_object *obj)
        if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
                pr_warning("%s is not an eBPF object file\n",
                        obj->path);
-               err = -EINVAL;
+               err = -LIBBPF_ERRNO__FORMAT;
                goto errout;
        }
 
@@ -374,14 +428,14 @@ bpf_object__check_endianness(struct bpf_object *obj)
                        goto mismatch;
                break;
        default:
-               return -EINVAL;
+               return -LIBBPF_ERRNO__ENDIAN;
        }
 
        return 0;
 
 mismatch:
        pr_warning("Error: endianness mismatch.\n");
-       return -EINVAL;
+       return -LIBBPF_ERRNO__ENDIAN;
 }
 
 static int
@@ -402,7 +456,7 @@ bpf_object__init_kversion(struct bpf_object *obj,
 
        if (size != sizeof(kver)) {
                pr_warning("invalid kver section in %s\n", obj->path);
-               return -EINVAL;
+               return -LIBBPF_ERRNO__FORMAT;
        }
        memcpy(&kver, data, sizeof(kver));
        obj->kern_version = kver;
@@ -444,7 +498,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
        if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
                pr_warning("failed to get e_shstrndx from %s\n",
                           obj->path);
-               return -EINVAL;
+               return -LIBBPF_ERRNO__FORMAT;
        }
 
        while ((scn = elf_nextscn(elf, scn)) != NULL) {
@@ -456,7 +510,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                if (gelf_getshdr(scn, &sh) != &sh) {
                        pr_warning("failed to get section header from %s\n",
                                   obj->path);
-                       err = -EINVAL;
+                       err = -LIBBPF_ERRNO__FORMAT;
                        goto out;
                }
 
@@ -464,7 +518,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                if (!name) {
                        pr_warning("failed to get section name from %s\n",
                                   obj->path);
-                       err = -EINVAL;
+                       err = -LIBBPF_ERRNO__FORMAT;
                        goto out;
                }
 
@@ -472,7 +526,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                if (!data) {
                        pr_warning("failed to get section data from %s(%s)\n",
                                   name, obj->path);
-                       err = -EINVAL;
+                       err = -LIBBPF_ERRNO__FORMAT;
                        goto out;
                }
                pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n",
@@ -495,7 +549,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                        if (obj->efile.symbols) {
                                pr_warning("bpf: multiple SYMTAB in %s\n",
                                           obj->path);
-                               err = -EEXIST;
+                               err = -LIBBPF_ERRNO__FORMAT;
                        } else
                                obj->efile.symbols = data;
                } else if ((sh.sh_type == SHT_PROGBITS) &&
@@ -504,7 +558,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                        err = bpf_object__add_program(obj, data->d_buf,
                                                      data->d_size, name, idx);
                        if (err) {
-                               char errmsg[128];
+                               char errmsg[STRERR_BUFSIZE];
+
                                strerror_r(-err, errmsg, sizeof(errmsg));
                                pr_warning("failed to alloc program %s (%s): %s",
                                           name, obj->path, errmsg);
@@ -576,7 +631,7 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 
                if (!gelf_getrel(data, i, &rel)) {
                        pr_warning("relocation: failed to get %d reloc\n", i);
-                       return -EINVAL;
+                       return -LIBBPF_ERRNO__FORMAT;
                }
 
                insn_idx = rel.r_offset / sizeof(struct bpf_insn);
@@ -587,20 +642,20 @@ bpf_program__collect_reloc(struct bpf_program *prog,
                                 &sym)) {
                        pr_warning("relocation: symbol %"PRIx64" not found\n",
                                   GELF_R_SYM(rel.r_info));
-                       return -EINVAL;
+                       return -LIBBPF_ERRNO__FORMAT;
                }
 
                if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
                        pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
                                   insn_idx, insns[insn_idx].code);
-                       return -EINVAL;
+                       return -LIBBPF_ERRNO__RELOC;
                }
 
                map_idx = sym.st_value / sizeof(struct bpf_map_def);
                if (map_idx >= nr_maps) {
                        pr_warning("bpf relocation: map_idx %d large than %d\n",
                                   (int)map_idx, (int)nr_maps - 1);
-                       return -EINVAL;
+                       return -LIBBPF_ERRNO__RELOC;
                }
 
                prog->reloc_desc[i].insn_idx = insn_idx;
@@ -683,7 +738,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds)
                if (insn_idx >= (int)prog->insns_cnt) {
                        pr_warning("relocation out of range: '%s'\n",
                                   prog->section_name);
-                       return -ERANGE;
+                       return -LIBBPF_ERRNO__RELOC;
                }
                insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
                insns[insn_idx].imm = map_fds[map_idx];
@@ -721,7 +776,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 
        if (!obj_elf_valid(obj)) {
                pr_warning("Internal error: elf object is closed\n");
-               return -EINVAL;
+               return -LIBBPF_ERRNO__INTERNAL;
        }
 
        for (i = 0; i < obj->efile.nr_reloc; i++) {
@@ -734,21 +789,21 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 
                if (shdr->sh_type != SHT_REL) {
                        pr_warning("internal error at %d\n", __LINE__);
-                       return -EINVAL;
+                       return -LIBBPF_ERRNO__INTERNAL;
                }
 
                prog = bpf_object__find_prog_by_idx(obj, idx);
                if (!prog) {
                        pr_warning("relocation failed: no %d section\n",
                                   idx);
-                       return -ENOENT;
+                       return -LIBBPF_ERRNO__RELOC;
                }
 
                err = bpf_program__collect_reloc(prog, nr_maps,
                                                 shdr, data,
                                                 obj->efile.symbols);
                if (err)
-                       return -EINVAL;
+                       return err;
        }
        return 0;
 }
@@ -777,13 +832,23 @@ load_program(struct bpf_insn *insns, int insns_cnt,
                goto out;
        }
 
-       ret = -EINVAL;
+       ret = -LIBBPF_ERRNO__LOAD;
        pr_warning("load bpf program failed: %s\n", strerror(errno));
 
-       if (log_buf) {
+       if (log_buf && log_buf[0] != '\0') {
+               ret = -LIBBPF_ERRNO__VERIFY;
                pr_warning("-- BEGIN DUMP LOG ---\n");
                pr_warning("\n%s\n", log_buf);
                pr_warning("-- END LOG --\n");
+       } else {
+               if (insns_cnt >= BPF_MAXINSNS) {
+                       pr_warning("Program too large (%d insns), at most %d insns\n",
+                                  insns_cnt, BPF_MAXINSNS);
+                       ret = -LIBBPF_ERRNO__PROG2BIG;
+               } else if (log_buf) {
+                       pr_warning("log buffer is empty\n");
+                       ret = -LIBBPF_ERRNO__KVER;
+               }
        }
 
 out:
@@ -831,7 +896,7 @@ static int bpf_object__validate(struct bpf_object *obj)
        if (obj->kern_version == 0) {
                pr_warning("%s doesn't provide kernel version\n",
                           obj->path);
-               return -EINVAL;
+               return -LIBBPF_ERRNO__KVERSION;
        }
        return 0;
 }
@@ -840,32 +905,28 @@ static struct bpf_object *
 __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz)
 {
        struct bpf_object *obj;
+       int err;
 
        if (elf_version(EV_CURRENT) == EV_NONE) {
                pr_warning("failed to init libelf for %s\n", path);
-               return NULL;
+               return ERR_PTR(-LIBBPF_ERRNO__LIBELF);
        }
 
        obj = bpf_object__new(path, obj_buf, obj_buf_sz);
-       if (!obj)
-               return NULL;
+       if (IS_ERR(obj))
+               return obj;
 
-       if (bpf_object__elf_init(obj))
-               goto out;
-       if (bpf_object__check_endianness(obj))
-               goto out;
-       if (bpf_object__elf_collect(obj))
-               goto out;
-       if (bpf_object__collect_reloc(obj))
-               goto out;
-       if (bpf_object__validate(obj))
-               goto out;
+       CHECK_ERR(bpf_object__elf_init(obj), err, out);
+       CHECK_ERR(bpf_object__check_endianness(obj), err, out);
+       CHECK_ERR(bpf_object__elf_collect(obj), err, out);
+       CHECK_ERR(bpf_object__collect_reloc(obj), err, out);
+       CHECK_ERR(bpf_object__validate(obj), err, out);
 
        bpf_object__elf_finish(obj);
        return obj;
 out:
        bpf_object__close(obj);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 struct bpf_object *bpf_object__open(const char *path)
@@ -922,6 +983,8 @@ int bpf_object__unload(struct bpf_object *obj)
 
 int bpf_object__load(struct bpf_object *obj)
 {
+       int err;
+
        if (!obj)
                return -EINVAL;
 
@@ -931,18 +994,16 @@ int bpf_object__load(struct bpf_object *obj)
        }
 
        obj->loaded = true;
-       if (bpf_object__create_maps(obj))
-               goto out;
-       if (bpf_object__relocate(obj))
-               goto out;
-       if (bpf_object__load_progs(obj))
-               goto out;
+
+       CHECK_ERR(bpf_object__create_maps(obj), err, out);
+       CHECK_ERR(bpf_object__relocate(obj), err, out);
+       CHECK_ERR(bpf_object__load_progs(obj), err, out);
 
        return 0;
 out:
        bpf_object__unload(obj);
        pr_warning("failed to load object '%s'\n", obj->path);
-       return -EINVAL;
+       return err;
 }
 
 void bpf_object__close(struct bpf_object *obj)
@@ -990,10 +1051,18 @@ const char *
 bpf_object__get_name(struct bpf_object *obj)
 {
        if (!obj)
-               return NULL;
+               return ERR_PTR(-EINVAL);
        return obj->path;
 }
 
+unsigned int
+bpf_object__get_kversion(struct bpf_object *obj)
+{
+       if (!obj)
+               return 0;
+       return obj->kern_version;
+}
+
 struct bpf_program *
 bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
 {
@@ -1034,16 +1103,16 @@ int bpf_program__get_private(struct bpf_program *prog, void **ppriv)
        return 0;
 }
 
-const char *bpf_program__title(struct bpf_program *prog, bool dup)
+const char *bpf_program__title(struct bpf_program *prog, bool needs_copy)
 {
        const char *title;
 
        title = prog->section_name;
-       if (dup) {
+       if (needs_copy) {
                title = strdup(title);
                if (!title) {
                        pr_warning("failed to strdup program title\n");
-                       return NULL;
+                       return ERR_PTR(-ENOMEM);
                }
        }
 
index f16170c95ffdc2306aa02f836092661b2673408e..c9a9aef2806cbfbef033668920ab8cae02ca2e8d 100644 (file)
 
 #include <stdio.h>
 #include <stdbool.h>
+#include <linux/err.h>
+
+enum libbpf_errno {
+       __LIBBPF_ERRNO__START = 4000,
+
+       /* Something wrong in libelf */
+       LIBBPF_ERRNO__LIBELF = __LIBBPF_ERRNO__START,
+       LIBBPF_ERRNO__FORMAT,   /* BPF object format invalid */
+       LIBBPF_ERRNO__KVERSION, /* Incorrect or no 'version' section */
+       LIBBPF_ERRNO__ENDIAN,   /* Endian missmatch */
+       LIBBPF_ERRNO__INTERNAL, /* Internal error in libbpf */
+       LIBBPF_ERRNO__RELOC,    /* Relocation failed */
+       LIBBPF_ERRNO__LOAD,     /* Load program failure for unknown reason */
+       LIBBPF_ERRNO__VERIFY,   /* Kernel verifier blocks program loading */
+       LIBBPF_ERRNO__PROG2BIG, /* Program too big */
+       LIBBPF_ERRNO__KVER,     /* Incorrect kernel version */
+       __LIBBPF_ERRNO__END,
+};
+
+int libbpf_strerror(int err, char *buf, size_t size);
 
 /*
  * In include/linux/compiler-gcc.h, __printf is defined. However
@@ -36,6 +56,7 @@ void bpf_object__close(struct bpf_object *object);
 int bpf_object__load(struct bpf_object *obj);
 int bpf_object__unload(struct bpf_object *obj);
 const char *bpf_object__get_name(struct bpf_object *obj);
+unsigned int bpf_object__get_kversion(struct bpf_object *obj);
 
 struct bpf_object *bpf_object__next(struct bpf_object *prev);
 #define bpf_object__for_each_safe(pos, tmp)                    \
@@ -63,7 +84,7 @@ int bpf_program__set_private(struct bpf_program *prog, void *priv,
 int bpf_program__get_private(struct bpf_program *prog,
                             void **ppriv);
 
-const char *bpf_program__title(struct bpf_program *prog, bool dup);
+const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
 
 int bpf_program__fd(struct bpf_program *prog);
 
index 8ef602f18a32b9a19c7645488bd2bc8c757c30c6..9be663340f0a4c48e9ec51c996b13c3a8b596fdc 100644 (file)
@@ -18,7 +18,7 @@ __attribute__((constructor)) static void liblockdep_init(void)
 
 __attribute__((destructor)) static void liblockdep_exit(void)
 {
-       debug_check_no_locks_held(&current_obj);
+       debug_check_no_locks_held();
 }
 
 struct task_struct *__curr(void)
index 0bda630027c30324ddf74c021ab8465c749b6833..a60c14b9662aefd6f17b47dec534bce2f53d9f03 100644 (file)
@@ -43,6 +43,8 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                        struct lockdep_map *nest_lock, unsigned long ip);
 void lock_release(struct lockdep_map *lock, int nested,
                        unsigned long ip);
+extern void debug_check_no_locks_freed(const void *from, unsigned long len);
+extern void lockdep_init(void);
 
 #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
        { .name = (_name), .key = (void *)(_key), }
index 7ac838a1f196ca673b441341f5c3976a32b30fdb..6386dc3182a0985a40551d0af980e53102e04c2a 100644 (file)
@@ -3,5 +3,7 @@
 
 #define __used         __attribute__((__unused__))
 #define unlikely
+#define WRITE_ONCE(x, val) x=(val)
+#define RCU_INIT_POINTER(p, v) p=(v)
 
 #endif
index c1552c28507e472159ebd3fecee88811e51ff263..c808c7d02d21c86732c2aab981ccebd0dad71aad 100644 (file)
@@ -6,7 +6,7 @@
 #include <string.h>
 #include <limits.h>
 #include <linux/utsname.h>
-
+#include <linux/compiler.h>
 
 #define MAX_LOCK_DEPTH 2000UL
 
@@ -54,5 +54,6 @@ static struct new_utsname *init_utsname(void)
 #define static_obj(x) 1
 
 #define debug_show_all_locks()
+extern void debug_check_no_locks_held(void);
 
 #endif
index ee577ea03ba50f05a4b14379ddcd17a3f73593c0..ddf8880106524c1b2882122b3e5ed76f3c5cc3f6 100644 (file)
@@ -4,6 +4,9 @@ CC = gcc
 LEX = flex
 YACC = bison
 
+CFLAGS += -Wall -O2
+CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
+
 %.yacc.c: %.y
        $(YACC) -o $@ -d $<
 
@@ -12,15 +15,13 @@ YACC = bison
 
 all : bpf_jit_disasm bpf_dbg bpf_asm
 
-bpf_jit_disasm : CFLAGS = -Wall -O2 -DPACKAGE='bpf_jit_disasm'
+bpf_jit_disasm : CFLAGS += -DPACKAGE='bpf_jit_disasm'
 bpf_jit_disasm : LDLIBS = -lopcodes -lbfd -ldl
 bpf_jit_disasm : bpf_jit_disasm.o
 
-bpf_dbg : CFLAGS = -Wall -O2
 bpf_dbg : LDLIBS = -lreadline
 bpf_dbg : bpf_dbg.o
 
-bpf_asm : CFLAGS = -Wall -O2 -I.
 bpf_asm : LDLIBS =
 bpf_asm : bpf_asm.o bpf_exp.yacc.o bpf_exp.lex.o
 bpf_exp.lex.o : bpf_exp.yacc.c
index 7ea078658a875029fb0ad03101bacdbe45e31564..13293de8869fe932c9610f3a3c5612c838a65bc4 100644 (file)
@@ -62,7 +62,6 @@ OPTIONS
 --verbose=::
         Verbosity level.
 
--i::
 --no-inherit::
        Child tasks do not inherit counters.
 
index 480546d5f13b205b85790c9512d51f33693e73a1..dcd9a70c7193b43b5791058b01a3773da6e0d870 100644 (file)
@@ -78,7 +78,7 @@ clean:
 # The build-test target is not really parallel, don't print the jobs info:
 #
 build-test:
-       @$(MAKE) -f tests/make --no-print-directory
+       @$(MAKE) SHUF=1 -f tests/make --no-print-directory
 
 #
 # All other targets get passed through:
index 0a945d2e8ca5b1bd319fa18537e7a4c57e3b7291..99d127fe9c35e500ca74ea871fd4373fcea15d68 100644 (file)
@@ -675,6 +675,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                        .fork           = perf_event__repipe,
                        .exit           = perf_event__repipe,
                        .lost           = perf_event__repipe,
+                       .lost_samples   = perf_event__repipe,
                        .aux            = perf_event__repipe,
                        .itrace_start   = perf_event__repipe,
                        .context_switch = perf_event__repipe,
index 2853ad2bd43541b1291292f94a5c6f8a6804dd03..f256fac1e722527a18e585ed51a591c15c574207 100644 (file)
@@ -44,7 +44,7 @@
 struct report {
        struct perf_tool        tool;
        struct perf_session     *session;
-       bool                    force, use_tui, use_gtk, use_stdio;
+       bool                    use_tui, use_gtk, use_stdio;
        bool                    hide_unresolved;
        bool                    dont_use_callchains;
        bool                    show_full_info;
@@ -678,7 +678,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                   "file", "vmlinux pathname"),
        OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
                   "file", "kallsyms pathname"),
-       OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
+       OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
        OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
                    "load module symbols - WARNING: use only with -k and LIVE kernel"),
        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
@@ -832,7 +832,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        }
 
        file.path  = input_name;
-       file.force = report.force;
+       file.force = symbol_conf.force;
 
 repeat:
        session = perf_session__new(&file, false, &report.tool);
index 0ee6d900e100a29ceeb3cacf7e97d81dce8f8d17..e3d3e32c0a934dc8fd5ce207073f3b80ecf4361a 100644 (file)
@@ -1203,12 +1203,13 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
 
 static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
 {
+       if (l->thread == r->thread)
+               return 0;
        if (l->thread->tid < r->thread->tid)
                return -1;
        if (l->thread->tid > r->thread->tid)
                return 1;
-
-       return 0;
+       return (int)(l->thread - r->thread);
 }
 
 static int avg_cmp(struct work_atoms *l, struct work_atoms *r)
index 2f438f76cceb2cb1681c30d62324e6a03c4b2108..e77880b5094ded75ac4975d4212f9e35bb9cfa2f 100644 (file)
@@ -122,6 +122,9 @@ static bool                 forever                         = false;
 static struct timespec         ref_time;
 static struct cpu_map          *aggr_map;
 static aggr_get_id_t           aggr_get_id;
+static bool                    append_file;
+static const char              *output_name;
+static int                     output_fd;
 
 static volatile int done = 0;
 
@@ -513,15 +516,6 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
-
-       if (csv_output || stat_config.interval)
-               return;
-
-       if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
-               fprintf(output, " # %8.3f CPUs utilized          ",
-                       avg / avg_stats(&walltime_nsecs_stats));
-       else
-               fprintf(output, "                                   ");
 }
 
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
@@ -529,7 +523,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
        FILE *output = stat_config.output;
        double sc =  evsel->scale;
        const char *fmt;
-       int cpu = cpu_map__id_to_cpu(id);
 
        if (csv_output) {
                fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
@@ -542,9 +535,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
        aggr_printout(evsel, id, nr);
 
-       if (stat_config.aggr_mode == AGGR_GLOBAL)
-               cpu = 0;
-
        fprintf(output, fmt, avg, csv_sep);
 
        if (evsel->unit)
@@ -556,12 +546,24 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
+}
 
-       if (csv_output || stat_config.interval)
-               return;
+static void printout(int id, int nr, struct perf_evsel *counter, double uval)
+{
+       int cpu = cpu_map__id_to_cpu(id);
+
+       if (stat_config.aggr_mode == AGGR_GLOBAL)
+               cpu = 0;
 
-       perf_stat__print_shadow_stats(output, evsel, avg, cpu,
-                                     stat_config.aggr_mode);
+       if (nsec_counter(counter))
+               nsec_printout(id, nr, counter, uval);
+       else
+               abs_printout(id, nr, counter, uval);
+
+       if (!csv_output && !stat_config.interval)
+               perf_stat__print_shadow_stats(stat_config.output, counter,
+                                             uval, cpu,
+                                             stat_config.aggr_mode);
 }
 
 static void print_aggr(char *prefix)
@@ -617,12 +619,7 @@ static void print_aggr(char *prefix)
                                continue;
                        }
                        uval = val * counter->scale;
-
-                       if (nsec_counter(counter))
-                               nsec_printout(id, nr, counter, uval);
-                       else
-                               abs_printout(id, nr, counter, uval);
-
+                       printout(id, nr, counter, uval);
                        if (!csv_output)
                                print_noise(counter, 1.0);
 
@@ -653,11 +650,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
                        fprintf(output, "%s", prefix);
 
                uval = val * counter->scale;
-
-               if (nsec_counter(counter))
-                       nsec_printout(thread, 0, counter, uval);
-               else
-                       abs_printout(thread, 0, counter, uval);
+               printout(thread, 0, counter, uval);
 
                if (!csv_output)
                        print_noise(counter, 1.0);
@@ -707,11 +700,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
        }
 
        uval = avg * counter->scale;
-
-       if (nsec_counter(counter))
-               nsec_printout(-1, 0, counter, uval);
-       else
-               abs_printout(-1, 0, counter, uval);
+       printout(-1, 0, counter, uval);
 
        print_noise(counter, avg);
 
@@ -764,12 +753,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                }
 
                uval = val * counter->scale;
-
-               if (nsec_counter(counter))
-                       nsec_printout(cpu, 0, counter, uval);
-               else
-                       abs_printout(cpu, 0, counter, uval);
-
+               printout(cpu, 0, counter, uval);
                if (!csv_output)
                        print_noise(counter, 1.0);
                print_running(run, ena);
@@ -946,6 +930,67 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
        return 0;
 }
 
+static const struct option stat_options[] = {
+       OPT_BOOLEAN('T', "transaction", &transaction_run,
+                   "hardware transaction statistics"),
+       OPT_CALLBACK('e', "event", &evsel_list, "event",
+                    "event selector. use 'perf list' to list available events",
+                    parse_events_option),
+       OPT_CALLBACK(0, "filter", &evsel_list, "filter",
+                    "event filter", parse_filter),
+       OPT_BOOLEAN('i', "no-inherit", &no_inherit,
+                   "child tasks do not inherit counters"),
+       OPT_STRING('p', "pid", &target.pid, "pid",
+                  "stat events on existing process id"),
+       OPT_STRING('t', "tid", &target.tid, "tid",
+                  "stat events on existing thread id"),
+       OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
+                   "system-wide collection from all CPUs"),
+       OPT_BOOLEAN('g', "group", &group,
+                   "put the counters into a counter group"),
+       OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
+       OPT_INCR('v', "verbose", &verbose,
+                   "be more verbose (show counter open errors, etc)"),
+       OPT_INTEGER('r', "repeat", &run_count,
+                   "repeat command and print average + stddev (max: 100, forever: 0)"),
+       OPT_BOOLEAN('n', "null", &null_run,
+                   "null run - dont start any counters"),
+       OPT_INCR('d', "detailed", &detailed_run,
+                   "detailed run - start a lot of events"),
+       OPT_BOOLEAN('S', "sync", &sync_run,
+                   "call sync() before starting a run"),
+       OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
+                          "print large numbers with thousands\' separators",
+                          stat__set_big_num),
+       OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
+                   "list of cpus to monitor in system-wide"),
+       OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
+                   "disable CPU count aggregation", AGGR_NONE),
+       OPT_STRING('x', "field-separator", &csv_sep, "separator",
+                  "print counts with custom separator"),
+       OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+                    "monitor event in cgroup name only", parse_cgroups),
+       OPT_STRING('o', "output", &output_name, "file", "output file name"),
+       OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
+       OPT_INTEGER(0, "log-fd", &output_fd,
+                   "log output to fd, instead of stderr"),
+       OPT_STRING(0, "pre", &pre_cmd, "command",
+                       "command to run prior to the measured command"),
+       OPT_STRING(0, "post", &post_cmd, "command",
+                       "command to run after to the measured command"),
+       OPT_UINTEGER('I', "interval-print", &stat_config.interval,
+                   "print counts at regular interval in ms (>= 10)"),
+       OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
+                    "aggregate counts per processor socket", AGGR_SOCKET),
+       OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
+                    "aggregate counts per physical processor core", AGGR_CORE),
+       OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
+                    "aggregate counts per thread", AGGR_THREAD),
+       OPT_UINTEGER('D', "delay", &initial_delay,
+                    "ms to wait before starting measurement after program start"),
+       OPT_END()
+};
+
 static int perf_stat__get_socket(struct cpu_map *map, int cpu)
 {
        return cpu_map__get_socket(map, cpu, NULL);
@@ -1193,69 +1238,6 @@ static int add_default_attributes(void)
 
 int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       bool append_file = false;
-       int output_fd = 0;
-       const char *output_name = NULL;
-       const struct option options[] = {
-       OPT_BOOLEAN('T', "transaction", &transaction_run,
-                   "hardware transaction statistics"),
-       OPT_CALLBACK('e', "event", &evsel_list, "event",
-                    "event selector. use 'perf list' to list available events",
-                    parse_events_option),
-       OPT_CALLBACK(0, "filter", &evsel_list, "filter",
-                    "event filter", parse_filter),
-       OPT_BOOLEAN('i', "no-inherit", &no_inherit,
-                   "child tasks do not inherit counters"),
-       OPT_STRING('p', "pid", &target.pid, "pid",
-                  "stat events on existing process id"),
-       OPT_STRING('t', "tid", &target.tid, "tid",
-                  "stat events on existing thread id"),
-       OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
-                   "system-wide collection from all CPUs"),
-       OPT_BOOLEAN('g', "group", &group,
-                   "put the counters into a counter group"),
-       OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
-       OPT_INCR('v', "verbose", &verbose,
-                   "be more verbose (show counter open errors, etc)"),
-       OPT_INTEGER('r', "repeat", &run_count,
-                   "repeat command and print average + stddev (max: 100, forever: 0)"),
-       OPT_BOOLEAN('n', "null", &null_run,
-                   "null run - dont start any counters"),
-       OPT_INCR('d', "detailed", &detailed_run,
-                   "detailed run - start a lot of events"),
-       OPT_BOOLEAN('S', "sync", &sync_run,
-                   "call sync() before starting a run"),
-       OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
-                          "print large numbers with thousands\' separators",
-                          stat__set_big_num),
-       OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
-                   "list of cpus to monitor in system-wide"),
-       OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
-                   "disable CPU count aggregation", AGGR_NONE),
-       OPT_STRING('x', "field-separator", &csv_sep, "separator",
-                  "print counts with custom separator"),
-       OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
-                    "monitor event in cgroup name only", parse_cgroups),
-       OPT_STRING('o', "output", &output_name, "file", "output file name"),
-       OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
-       OPT_INTEGER(0, "log-fd", &output_fd,
-                   "log output to fd, instead of stderr"),
-       OPT_STRING(0, "pre", &pre_cmd, "command",
-                       "command to run prior to the measured command"),
-       OPT_STRING(0, "post", &post_cmd, "command",
-                       "command to run after to the measured command"),
-       OPT_UINTEGER('I', "interval-print", &stat_config.interval,
-                   "print counts at regular interval in ms (>= 10)"),
-       OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
-                    "aggregate counts per processor socket", AGGR_SOCKET),
-       OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
-                    "aggregate counts per physical processor core", AGGR_CORE),
-       OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
-                    "aggregate counts per thread", AGGR_THREAD),
-       OPT_UINTEGER('D', "delay", &initial_delay,
-                    "ms to wait before starting measurement after program start"),
-       OPT_END()
-       };
        const char * const stat_usage[] = {
                "perf stat [<options>] [<command>]",
                NULL
@@ -1271,7 +1253,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if (evsel_list == NULL)
                return -ENOMEM;
 
-       argc = parse_options(argc, argv, options, stat_usage,
+       argc = parse_options(argc, argv, stat_options, stat_usage,
                PARSE_OPT_STOP_AT_NON_OPTION);
 
        interval = stat_config.interval;
@@ -1281,14 +1263,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 
        if (output_name && output_fd) {
                fprintf(stderr, "cannot use both --output and --log-fd\n");
-               parse_options_usage(stat_usage, options, "o", 1);
-               parse_options_usage(NULL, options, "log-fd", 0);
+               parse_options_usage(stat_usage, stat_options, "o", 1);
+               parse_options_usage(NULL, stat_options, "log-fd", 0);
                goto out;
        }
 
        if (output_fd < 0) {
                fprintf(stderr, "argument to --log-fd must be a > 0\n");
-               parse_options_usage(stat_usage, options, "log-fd", 0);
+               parse_options_usage(stat_usage, stat_options, "log-fd", 0);
                goto out;
        }
 
@@ -1328,8 +1310,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                /* User explicitly passed -B? */
                if (big_num_opt == 1) {
                        fprintf(stderr, "-B option not supported with -x\n");
-                       parse_options_usage(stat_usage, options, "B", 1);
-                       parse_options_usage(NULL, options, "x", 1);
+                       parse_options_usage(stat_usage, stat_options, "B", 1);
+                       parse_options_usage(NULL, stat_options, "x", 1);
                        goto out;
                } else /* Nope, so disable big number formatting */
                        big_num = false;
@@ -1337,11 +1319,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                big_num = false;
 
        if (!argc && target__none(&target))
-               usage_with_options(stat_usage, options);
+               usage_with_options(stat_usage, stat_options);
 
        if (run_count < 0) {
                pr_err("Run count must be a positive number\n");
-               parse_options_usage(stat_usage, options, "r", 1);
+               parse_options_usage(stat_usage, stat_options, "r", 1);
                goto out;
        } else if (run_count == 0) {
                forever = true;
@@ -1351,8 +1333,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
                fprintf(stderr, "The --per-thread option is only available "
                        "when monitoring via -p -t options.\n");
-               parse_options_usage(NULL, options, "p", 1);
-               parse_options_usage(NULL, options, "t", 1);
+               parse_options_usage(NULL, stat_options, "p", 1);
+               parse_options_usage(NULL, stat_options, "t", 1);
                goto out;
        }
 
@@ -1366,9 +1348,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                fprintf(stderr, "both cgroup and no-aggregation "
                        "modes only available in system-wide mode\n");
 
-               parse_options_usage(stat_usage, options, "G", 1);
-               parse_options_usage(NULL, options, "A", 1);
-               parse_options_usage(NULL, options, "a", 1);
+               parse_options_usage(stat_usage, stat_options, "G", 1);
+               parse_options_usage(NULL, stat_options, "A", 1);
+               parse_options_usage(NULL, stat_options, "a", 1);
                goto out;
        }
 
@@ -1380,12 +1362,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if (perf_evlist__create_maps(evsel_list, &target) < 0) {
                if (target__has_task(&target)) {
                        pr_err("Problems finding threads of monitor\n");
-                       parse_options_usage(stat_usage, options, "p", 1);
-                       parse_options_usage(NULL, options, "t", 1);
+                       parse_options_usage(stat_usage, stat_options, "p", 1);
+                       parse_options_usage(NULL, stat_options, "t", 1);
                } else if (target__has_cpu(&target)) {
                        perror("failed to parse CPUs map");
-                       parse_options_usage(stat_usage, options, "C", 1);
-                       parse_options_usage(NULL, options, "a", 1);
+                       parse_options_usage(stat_usage, stat_options, "C", 1);
+                       parse_options_usage(NULL, stat_options, "a", 1);
                }
                goto out;
        }
@@ -1400,7 +1382,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if (interval && interval < 100) {
                if (interval < 10) {
                        pr_err("print interval must be >= 10ms\n");
-                       parse_options_usage(stat_usage, options, "I", 1);
+                       parse_options_usage(stat_usage, stat_options, "I", 1);
                        goto out;
                } else
                        pr_warning("print interval < 100ms. "
diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore
new file mode 100644 (file)
index 0000000..489fc9f
--- /dev/null
@@ -0,0 +1,2 @@
+llvm-src-base.c
+llvm-src-kbuild.c
index 50de2253cff6c64450a23d0332d22c43c802dd8f..f41ebf8849feb1d5fe20e2601de952c85e3bac8c 100644 (file)
@@ -31,9 +31,24 @@ perf-y += sample-parsing.o
 perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
-perf-y += llvm.o
+perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o
+perf-y += bpf.o
 perf-y += topology.o
 
+$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c
+       $(call rule_mkdir)
+       $(Q)echo '#include <tests/llvm.h>' > $@
+       $(Q)echo 'const char test_llvm__bpf_base_prog[] =' >> $@
+       $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+       $(Q)echo ';' >> $@
+
+$(OUTPUT)tests/llvm-src-kbuild.c: tests/bpf-script-test-kbuild.c
+       $(call rule_mkdir)
+       $(Q)echo '#include <tests/llvm.h>' > $@
+       $(Q)echo 'const char test_llvm__bpf_test_kbuild_prog[] =' >> $@
+       $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+       $(Q)echo ';' >> $@
+
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 endif
index 2dfc9ad0e6f2487d730008fac56988f9b408666d..638875a0960a1e8d8b786a4b7c73dab463050857 100644 (file)
@@ -171,6 +171,5 @@ int test__attr(void)
            !lstat(path_perf, &st))
                return run_dir(path_dir, path_perf);
 
-       fprintf(stderr, " (omitted)");
-       return 0;
+       return TEST_SKIP;
 }
index 410a70b93b934e0632cedeb7b42f4526198e7220..0ec9c2c031649377a2523deda904ea1a7c9284c0 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * bpf-script-example.c
+ * Test basic LLVM building
+ */
 #ifndef LINUX_VERSION_CODE
 # error Need LINUX_VERSION_CODE
 # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
diff --git a/tools/perf/tests/bpf-script-test-kbuild.c b/tools/perf/tests/bpf-script-test-kbuild.c
new file mode 100644 (file)
index 0000000..3626924
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * bpf-script-test-kbuild.c
+ * Test include from kernel header
+ */
+#ifndef LINUX_VERSION_CODE
+# error Need LINUX_VERSION_CODE
+# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
+#endif
+#define SEC(NAME) __attribute__((section(NAME), used))
+
+#include <uapi/linux/fs.h>
+#include <uapi/asm/ptrace.h>
+
+SEC("func=vfs_llseek")
+int bpf_func__vfs_llseek(void *ctx)
+{
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
new file mode 100644 (file)
index 0000000..ec16f78
--- /dev/null
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <sys/epoll.h>
+#include <util/bpf-loader.h>
+#include <util/evlist.h>
+#include "tests.h"
+#include "llvm.h"
+#include "debug.h"
+#define NR_ITERS       111
+
+#ifdef HAVE_LIBBPF_SUPPORT
+
+static int epoll_pwait_loop(void)
+{
+       int i;
+
+       /* Should fail NR_ITERS times */
+       for (i = 0; i < NR_ITERS; i++)
+               epoll_pwait(-(i + 1), NULL, 0, 0, NULL);
+       return 0;
+}
+
+static struct {
+       enum test_llvm__testcase prog_id;
+       const char *desc;
+       const char *name;
+       const char *msg_compile_fail;
+       const char *msg_load_fail;
+       int (*target_func)(void);
+       int expect_result;
+} bpf_testcase_table[] = {
+       {
+               LLVM_TESTCASE_BASE,
+               "Test basic BPF filtering",
+               "[basic_bpf_test]",
+               "fix 'perf test LLVM' first",
+               "load bpf object failed",
+               &epoll_pwait_loop,
+               (NR_ITERS + 1) / 2,
+       },
+};
+
+static int do_test(struct bpf_object *obj, int (*func)(void),
+                  int expect)
+{
+       struct record_opts opts = {
+               .target = {
+                       .uid = UINT_MAX,
+                       .uses_mmap = true,
+               },
+               .freq         = 0,
+               .mmap_pages   = 256,
+               .default_interval = 1,
+       };
+
+       char pid[16];
+       char sbuf[STRERR_BUFSIZE];
+       struct perf_evlist *evlist;
+       int i, ret = TEST_FAIL, err = 0, count = 0;
+
+       struct parse_events_evlist parse_evlist;
+       struct parse_events_error parse_error;
+
+       bzero(&parse_error, sizeof(parse_error));
+       bzero(&parse_evlist, sizeof(parse_evlist));
+       parse_evlist.error = &parse_error;
+       INIT_LIST_HEAD(&parse_evlist.list);
+
+       err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj);
+       if (err || list_empty(&parse_evlist.list)) {
+               pr_debug("Failed to add events selected by BPF\n");
+               if (!err)
+                       return TEST_FAIL;
+       }
+
+       snprintf(pid, sizeof(pid), "%d", getpid());
+       pid[sizeof(pid) - 1] = '\0';
+       opts.target.tid = opts.target.pid = pid;
+
+       /* Instead of perf_evlist__new_default, don't add default events */
+       evlist = perf_evlist__new();
+       if (!evlist) {
+               pr_debug("No ehough memory to create evlist\n");
+               return TEST_FAIL;
+       }
+
+       err = perf_evlist__create_maps(evlist, &opts.target);
+       if (err < 0) {
+               pr_debug("Not enough memory to create thread/cpu maps\n");
+               goto out_delete_evlist;
+       }
+
+       perf_evlist__splice_list_tail(evlist, &parse_evlist.list);
+       evlist->nr_groups = parse_evlist.nr_groups;
+
+       perf_evlist__config(evlist, &opts);
+
+       err = perf_evlist__open(evlist);
+       if (err < 0) {
+               pr_debug("perf_evlist__open: %s\n",
+                        strerror_r(errno, sbuf, sizeof(sbuf)));
+               goto out_delete_evlist;
+       }
+
+       err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
+       if (err < 0) {
+               pr_debug("perf_evlist__mmap: %s\n",
+                        strerror_r(errno, sbuf, sizeof(sbuf)));
+               goto out_delete_evlist;
+       }
+
+       perf_evlist__enable(evlist);
+       (*func)();
+       perf_evlist__disable(evlist);
+
+       for (i = 0; i < evlist->nr_mmaps; i++) {
+               union perf_event *event;
+
+               while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
+                       const u32 type = event->header.type;
+
+                       if (type == PERF_RECORD_SAMPLE)
+                               count ++;
+               }
+       }
+
+       if (count != expect)
+               pr_debug("BPF filter result incorrect\n");
+
+       ret = TEST_OK;
+
+out_delete_evlist:
+       perf_evlist__delete(evlist);
+       return ret;
+}
+
+static struct bpf_object *
+prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
+{
+       struct bpf_object *obj;
+
+       obj = bpf__prepare_load_buffer(obj_buf, obj_buf_sz, name);
+       if (IS_ERR(obj)) {
+               pr_debug("Compile BPF program failed.\n");
+               return NULL;
+       }
+       return obj;
+}
+
+static int __test__bpf(int index)
+{
+       int ret;
+       void *obj_buf;
+       size_t obj_buf_sz;
+       struct bpf_object *obj;
+
+       ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
+                                      bpf_testcase_table[index].prog_id,
+                                      true);
+       if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
+               pr_debug("Unable to get BPF object, %s\n",
+                        bpf_testcase_table[index].msg_compile_fail);
+               if (index == 0)
+                       return TEST_SKIP;
+               else
+                       return TEST_FAIL;
+       }
+
+       obj = prepare_bpf(obj_buf, obj_buf_sz,
+                         bpf_testcase_table[index].name);
+       if (!obj) {
+               ret = TEST_FAIL;
+               goto out;
+       }
+
+       ret = do_test(obj,
+                     bpf_testcase_table[index].target_func,
+                     bpf_testcase_table[index].expect_result);
+out:
+       bpf__clear();
+       return ret;
+}
+
+int test__bpf(void)
+{
+       unsigned int i;
+       int err;
+
+       if (geteuid() != 0) {
+               pr_debug("Only root can run BPF test\n");
+               return TEST_SKIP;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(bpf_testcase_table); i++) {
+               err = __test__bpf(i);
+
+               if (err != TEST_OK)
+                       return err;
+       }
+
+       return TEST_OK;
+}
+
+#else
+int test__bpf(void)
+{
+       pr_debug("Skip BPF test because BPF support is not compiled\n");
+       return TEST_SKIP;
+}
+#endif
index 66f72d3d66771ab4c9ad1cec7a53b92d8bcb8f1b..80c442eab767d0c333408c8daecbc32d3a120d0e 100644 (file)
@@ -165,6 +165,10 @@ static struct test generic_tests[] = {
                .desc = "Test topology in session",
                .func = test_session_topology,
        },
+       {
+               .desc = "Test BPF filter",
+               .func = test__bpf,
+       },
        {
                .func = NULL,
        },
@@ -192,7 +196,7 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char
                        continue;
                }
 
-               if (strstr(test->desc, argv[i]))
+               if (strcasestr(test->desc, argv[i]))
                        return true;
        }
 
index 49b1959dda41f0ceb5bc248f3c3e90b558ce9169..a767a6400c5ced49b16b9b4be7a3ea638799998d 100644 (file)
@@ -613,16 +613,16 @@ int test__code_reading(void)
        case TEST_CODE_READING_OK:
                return 0;
        case TEST_CODE_READING_NO_VMLINUX:
-               fprintf(stderr, " (no vmlinux)");
+               pr_debug("no vmlinux\n");
                return 0;
        case TEST_CODE_READING_NO_KCORE:
-               fprintf(stderr, " (no kcore)");
+               pr_debug("no kcore\n");
                return 0;
        case TEST_CODE_READING_NO_ACCESS:
-               fprintf(stderr, " (no access)");
+               pr_debug("no access\n");
                return 0;
        case TEST_CODE_READING_NO_KERNEL_OBJ:
-               fprintf(stderr, " (no kernel obj)");
+               pr_debug("no kernel obj\n");
                return 0;
        default:
                return -1;
index 4d4b9837b630ae9fd72cb0a404a4bae0e3864e14..a2e2269aa093a902f4810304d4af7e2fb8767b5c 100644 (file)
@@ -90,8 +90,8 @@ int test__keep_tracking(void)
        evsel->attr.enable_on_exec = 0;
 
        if (perf_evlist__open(evlist) < 0) {
-               fprintf(stderr, " (not supported)");
-               err = 0;
+               pr_debug("Unable to open dummy and cycles event\n");
+               err = TEST_SKIP;
                goto out_err;
        }
 
index 52d55971f66f6f569db38db00b87101e7aa61507..bc4cf507cde50b7018bac107e152ba9f23ab007d 100644 (file)
@@ -2,6 +2,7 @@
 #include <bpf/libbpf.h>
 #include <util/llvm-utils.h>
 #include <util/cache.h>
+#include "llvm.h"
 #include "tests.h"
 #include "debug.h"
 
@@ -11,42 +12,58 @@ static int perf_config_cb(const char *var, const char *val,
        return perf_default_config(var, val, arg);
 }
 
-/*
- * Randomly give it a "version" section since we don't really load it
- * into kernel
- */
-static const char test_bpf_prog[] =
-       "__attribute__((section(\"do_fork\"), used)) "
-       "int fork(void *ctx) {return 0;} "
-       "char _license[] __attribute__((section(\"license\"), used)) = \"GPL\";"
-       "int _version __attribute__((section(\"version\"), used)) = 0x40100;";
-
 #ifdef HAVE_LIBBPF_SUPPORT
 static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
 {
        struct bpf_object *obj;
 
        obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
-       if (!obj)
-               return -1;
+       if (IS_ERR(obj))
+               return TEST_FAIL;
        bpf_object__close(obj);
-       return 0;
+       return TEST_OK;
 }
 #else
 static int test__bpf_parsing(void *obj_buf __maybe_unused,
                             size_t obj_buf_sz __maybe_unused)
 {
-       fprintf(stderr, " (skip bpf parsing)");
-       return 0;
+       pr_debug("Skip bpf parsing\n");
+       return TEST_OK;
 }
 #endif
 
-int test__llvm(void)
+static struct {
+       const char *source;
+       const char *desc;
+} bpf_source_table[__LLVM_TESTCASE_MAX] = {
+       [LLVM_TESTCASE_BASE] = {
+               .source = test_llvm__bpf_base_prog,
+               .desc = "Basic BPF llvm compiling test",
+       },
+       [LLVM_TESTCASE_KBUILD] = {
+               .source = test_llvm__bpf_test_kbuild_prog,
+               .desc = "Test kbuild searching",
+       },
+};
+
+
+int
+test_llvm__fetch_bpf_obj(void **p_obj_buf,
+                        size_t *p_obj_buf_sz,
+                        enum test_llvm__testcase index,
+                        bool force)
 {
-       char *tmpl_new, *clang_opt_new;
-       void *obj_buf;
-       size_t obj_buf_sz;
-       int err, old_verbose;
+       const char *source;
+       const char *desc;
+       const char *tmpl_old, *clang_opt_old;
+       char *tmpl_new = NULL, *clang_opt_new = NULL;
+       int err, old_verbose, ret = TEST_FAIL;
+
+       if (index >= __LLVM_TESTCASE_MAX)
+               return TEST_FAIL;
+
+       source = bpf_source_table[index].source;
+       desc = bpf_source_table[index].desc;
 
        perf_config(perf_config_cb, NULL);
 
@@ -54,45 +71,100 @@ int test__llvm(void)
         * Skip this test if user's .perfconfig doesn't set [llvm] section
         * and clang is not found in $PATH, and this is not perf test -v
         */
-       if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) {
-               fprintf(stderr, " (no clang, try 'perf test -v LLVM')");
+       if (!force && (verbose == 0 &&
+                      !llvm_param.user_set_param &&
+                      llvm__search_clang())) {
+               pr_debug("No clang and no verbosive, skip this test\n");
                return TEST_SKIP;
        }
 
-       old_verbose = verbose;
        /*
         * llvm is verbosity when error. Suppress all error output if
         * not 'perf test -v'.
         */
+       old_verbose = verbose;
        if (verbose == 0)
                verbose = -1;
 
+       *p_obj_buf = NULL;
+       *p_obj_buf_sz = 0;
+
        if (!llvm_param.clang_bpf_cmd_template)
-               return -1;
+               goto out;
 
        if (!llvm_param.clang_opt)
                llvm_param.clang_opt = strdup("");
 
-       err = asprintf(&tmpl_new, "echo '%s' | %s", test_bpf_prog,
-                      llvm_param.clang_bpf_cmd_template);
+       err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
+                      llvm_param.clang_bpf_cmd_template,
+                      old_verbose ? "" : " 2>/dev/null");
        if (err < 0)
-               return -1;
+               goto out;
        err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
        if (err < 0)
-               return -1;
+               goto out;
 
+       tmpl_old = llvm_param.clang_bpf_cmd_template;
        llvm_param.clang_bpf_cmd_template = tmpl_new;
+       clang_opt_old = llvm_param.clang_opt;
        llvm_param.clang_opt = clang_opt_new;
-       err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz);
+
+       err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
+
+       llvm_param.clang_bpf_cmd_template = tmpl_old;
+       llvm_param.clang_opt = clang_opt_old;
 
        verbose = old_verbose;
-       if (err) {
-               if (!verbose)
-                       fprintf(stderr, " (use -v to see error message)");
-               return -1;
-       }
+       if (err)
+               goto out;
+
+       ret = TEST_OK;
+out:
+       free(tmpl_new);
+       free(clang_opt_new);
+       if (ret != TEST_OK)
+               pr_debug("Failed to compile test case: '%s'\n", desc);
+       return ret;
+}
+
+int test__llvm(void)
+{
+       enum test_llvm__testcase i;
+
+       for (i = 0; i < __LLVM_TESTCASE_MAX; i++) {
+               int ret;
+               void *obj_buf = NULL;
+               size_t obj_buf_sz = 0;
+
+               ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
+                                              i, false);
 
-       err = test__bpf_parsing(obj_buf, obj_buf_sz);
-       free(obj_buf);
-       return err;
+               if (ret == TEST_OK) {
+                       ret = test__bpf_parsing(obj_buf, obj_buf_sz);
+                       if (ret != TEST_OK)
+                               pr_debug("Failed to parse test case '%s'\n",
+                                        bpf_source_table[i].desc);
+               }
+               free(obj_buf);
+
+               switch (ret) {
+               case TEST_SKIP:
+                       return TEST_SKIP;
+               case TEST_OK:
+                       break;
+               default:
+                       /*
+                        * Test 0 is the basic LLVM test. If test 0
+                        * fail, the basic LLVM support not functional
+                        * so the whole test should fail. If other test
+                        * case fail, it can be fixed by adjusting
+                        * config so don't report error.
+                        */
+                       if (i == 0)
+                               return TEST_FAIL;
+                       else
+                               return TEST_SKIP;
+               }
+       }
+       return TEST_OK;
 }
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
new file mode 100644 (file)
index 0000000..d91d8f4
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef PERF_TEST_LLVM_H
+#define PERF_TEST_LLVM_H
+
+#include <stddef.h> /* for size_t */
+#include <stdbool.h> /* for bool */
+
+extern const char test_llvm__bpf_base_prog[];
+extern const char test_llvm__bpf_test_kbuild_prog[];
+
+enum test_llvm__testcase {
+       LLVM_TESTCASE_BASE,
+       LLVM_TESTCASE_KBUILD,
+       __LLVM_TESTCASE_MAX,
+};
+
+int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
+                            enum test_llvm__testcase index, bool force);
+#endif
index 2cbd0c6901e35ff3954bf06892bb02b3c9f92cef..8ea3dffc5065fbc532ebfe5a170d64f33f18ed3d 100644 (file)
@@ -221,6 +221,11 @@ test_O = $(if $(test_$1),$(test_$1),$(test_default_O))
 
 all:
 
+ifdef SHUF
+run := $(shell shuf -e $(run))
+run_O := $(shell shuf -e $(run_O))
+endif
+
 ifdef DEBUG
 d := $(info run   $(run))
 d := $(info run_O $(run_O))
index e698742d4fec3300ac6c6b00bf55696414567dd4..a02af503100c9c51c1f961c9e089546ccdcfd000 100644 (file)
@@ -366,7 +366,7 @@ int test__switch_tracking(void)
 
        /* Third event */
        if (!perf_evlist__can_select_event(evlist, sched_switch)) {
-               fprintf(stderr, " (no sched_switch)");
+               pr_debug("No sched_switch\n");
                err = 0;
                goto out;
        }
@@ -442,7 +442,7 @@ int test__switch_tracking(void)
        }
 
        if (perf_evlist__open(evlist) < 0) {
-               fprintf(stderr, " (not supported)");
+               pr_debug("Not supported\n");
                err = 0;
                goto out;
        }
index c80486969f83412621336a33ee95edef87d2fb31..3c8734a3abbc5ba24c9feb90c3cbdf3c5c1dfc7e 100644 (file)
@@ -66,6 +66,7 @@ int test__fdarray__add(void);
 int test__kmod_path__parse(void);
 int test__thread_map(void);
 int test__llvm(void);
+int test__bpf(void);
 int test_session_topology(void);
 
 #if defined(__arm__) || defined(__aarch64__)
index e5afb893604044f189da5a0f50962f990362e0da..fa9eb92c9e24a477e45623c1017a2791fc68dd07 100644 (file)
@@ -1430,7 +1430,6 @@ static int switch_data_file(void)
 
 struct popup_action {
        struct thread           *thread;
-       struct dso              *dso;
        struct map_symbol       ms;
        int                     socket;
 
@@ -1565,7 +1564,6 @@ add_dso_opt(struct hist_browser *browser, struct popup_action *act,
                return 0;
 
        act->ms.map = map;
-       act->dso = map->dso;
        act->fn = do_zoom_dso;
        return 1;
 }
@@ -1827,7 +1825,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
        while (1) {
                struct thread *thread = NULL;
-               struct dso *dso = NULL;
                struct map *map = NULL;
                int choice = 0;
                int socked_id = -1;
@@ -1839,8 +1836,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                if (browser->he_selection != NULL) {
                        thread = hist_browser__selected_thread(browser);
                        map = browser->selection->map;
-                       if (map)
-                               dso = map->dso;
                        socked_id = browser->he_selection->socket;
                }
                switch (key) {
@@ -1874,7 +1869,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        hist_browser__dump(browser);
                        continue;
                case 'd':
-                       actions->dso = dso;
+                       actions->ms.map = map;
                        do_zoom_dso(browser, actions);
                        continue;
                case 'V':
index 0fc8d7a2fea5f2ddee03789c3c0b442278f0fb0a..1dd1949b0e7995e43f0fa216fee0db583803ed5c 100644 (file)
@@ -1084,6 +1084,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
        struct kcore_extract kce;
        bool delete_extract = false;
        int lineno = 0;
+       int nline;
 
        if (filename)
                symbol__join_symfs(symfs_filename, filename);
@@ -1179,6 +1180,9 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
 
                ret = decompress_to_file(m.ext, symfs_filename, fd);
 
+               if (ret)
+                       pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
+
                free(m.ext);
                close(fd);
 
@@ -1204,13 +1208,25 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
        pr_debug("Executing: %s\n", command);
 
        file = popen(command, "r");
-       if (!file)
+       if (!file) {
+               pr_err("Failure running %s\n", command);
+               /*
+                * If we were using debug info should retry with
+                * original binary.
+                */
                goto out_remove_tmp;
+       }
 
-       while (!feof(file))
+       nline = 0;
+       while (!feof(file)) {
                if (symbol__parse_objdump_line(sym, map, file, privsize,
                            &lineno) < 0)
                        break;
+               nline++;
+       }
+
+       if (nline == 0)
+               pr_err("No output from %s\n", command);
 
        /*
         * kallsyms does not have symbol sizes so there may a nop at the end.
@@ -1604,6 +1620,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
        len = symbol__size(sym);
 
        if (print_lines) {
+               srcline_full_filename = full_paths;
                symbol__get_source_line(sym, map, evsel, &source_line, len);
                print_summary(&source_line, dso->long_name);
        }
index ba6f7526b282805c62337479926256949fe09bfc..4c50411371db31208c361115331695571fe545b7 100644 (file)
@@ -26,18 +26,40 @@ static int libbpf_##name(const char *fmt, ...)      \
        return ret;                             \
 }
 
-DEFINE_PRINT_FN(warning, 0)
-DEFINE_PRINT_FN(info, 0)
+DEFINE_PRINT_FN(warning, 1)
+DEFINE_PRINT_FN(info, 1)
 DEFINE_PRINT_FN(debug, 1)
 
 struct bpf_prog_priv {
        struct perf_probe_event pev;
 };
 
+static bool libbpf_initialized;
+
+struct bpf_object *
+bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
+{
+       struct bpf_object *obj;
+
+       if (!libbpf_initialized) {
+               libbpf_set_print(libbpf_warning,
+                                libbpf_info,
+                                libbpf_debug);
+               libbpf_initialized = true;
+       }
+
+       obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name);
+       if (IS_ERR(obj)) {
+               pr_debug("bpf: failed to load buffer\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       return obj;
+}
+
 struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 {
        struct bpf_object *obj;
-       static bool libbpf_initialized;
 
        if (!libbpf_initialized) {
                libbpf_set_print(libbpf_warning,
@@ -53,15 +75,15 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
 
                err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
                if (err)
-                       return ERR_PTR(err);
+                       return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
                obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
                free(obj_buf);
        } else
                obj = bpf_object__open(filename);
 
-       if (!obj) {
+       if (IS_ERR(obj)) {
                pr_debug("bpf: failed to load %s\n", filename);
-               return ERR_PTR(-EINVAL);
+               return obj;
        }
 
        return obj;
@@ -96,9 +118,9 @@ config_bpf_program(struct bpf_program *prog)
        int err;
 
        config_str = bpf_program__title(prog, false);
-       if (!config_str) {
+       if (IS_ERR(config_str)) {
                pr_debug("bpf: unable to get title for program\n");
-               return -EINVAL;
+               return PTR_ERR(config_str);
        }
 
        priv = calloc(sizeof(*priv), 1);
@@ -113,14 +135,14 @@ config_bpf_program(struct bpf_program *prog)
        if (err < 0) {
                pr_debug("bpf: '%s' is not a valid config string\n",
                         config_str);
-               err = -EINVAL;
+               err = -BPF_LOADER_ERRNO__CONFIG;
                goto errout;
        }
 
        if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
                pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
                         config_str, PERF_BPF_PROBE_GROUP);
-               err = -EINVAL;
+               err = -BPF_LOADER_ERRNO__GROUP;
                goto errout;
        } else if (!pev->group)
                pev->group = strdup(PERF_BPF_PROBE_GROUP);
@@ -132,9 +154,9 @@ config_bpf_program(struct bpf_program *prog)
        }
 
        if (!pev->event) {
-               pr_debug("bpf: '%s': event name is missing\n",
+               pr_debug("bpf: '%s': event name is missing. Section name should be 'key=value'\n",
                         config_str);
-               err = -EINVAL;
+               err = -BPF_LOADER_ERRNO__EVENTNAME;
                goto errout;
        }
        pr_debug("bpf: config '%s' is ok\n", config_str);
@@ -285,7 +307,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
                                (void **)&priv);
                if (err || !priv) {
                        pr_debug("bpf: failed to get private field\n");
-                       return -EINVAL;
+                       return -BPF_LOADER_ERRNO__INTERNAL;
                }
 
                pev = &priv->pev;
@@ -308,13 +330,57 @@ int bpf__foreach_tev(struct bpf_object *obj,
        return 0;
 }
 
+#define ERRNO_OFFSET(e)                ((e) - __BPF_LOADER_ERRNO__START)
+#define ERRCODE_OFFSET(c)      ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
+#define NR_ERRNO       (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
+
+static const char *bpf_loader_strerror_table[NR_ERRNO] = {
+       [ERRCODE_OFFSET(CONFIG)]        = "Invalid config string",
+       [ERRCODE_OFFSET(GROUP)]         = "Invalid group name",
+       [ERRCODE_OFFSET(EVENTNAME)]     = "No event name found in config string",
+       [ERRCODE_OFFSET(INTERNAL)]      = "BPF loader internal error",
+       [ERRCODE_OFFSET(COMPILE)]       = "Error when compiling BPF scriptlet",
+};
+
+static int
+bpf_loader_strerror(int err, char *buf, size_t size)
+{
+       char sbuf[STRERR_BUFSIZE];
+       const char *msg;
+
+       if (!buf || !size)
+               return -1;
+
+       err = err > 0 ? err : -err;
+
+       if (err >= __LIBBPF_ERRNO__START)
+               return libbpf_strerror(err, buf, size);
+
+       if (err >= __BPF_LOADER_ERRNO__START && err < __BPF_LOADER_ERRNO__END) {
+               msg = bpf_loader_strerror_table[ERRNO_OFFSET(err)];
+               snprintf(buf, size, "%s", msg);
+               buf[size - 1] = '\0';
+               return 0;
+       }
+
+       if (err >= __BPF_LOADER_ERRNO__END)
+               snprintf(buf, size, "Unknown bpf loader error %d", err);
+       else
+               snprintf(buf, size, "%s",
+                        strerror_r(err, sbuf, sizeof(sbuf)));
+
+       buf[size - 1] = '\0';
+       return -1;
+}
+
 #define bpf__strerror_head(err, buf, size) \
        char sbuf[STRERR_BUFSIZE], *emsg;\
        if (!size)\
                return 0;\
        if (err < 0)\
                err = -err;\
-       emsg = strerror_r(err, sbuf, sizeof(sbuf));\
+       bpf_loader_strerror(err, sbuf, sizeof(sbuf));\
+       emsg = sbuf;\
        switch (err) {\
        default:\
                scnprintf(buf, size, "%s", emsg);\
@@ -330,23 +396,62 @@ int bpf__foreach_tev(struct bpf_object *obj,
        }\
        buf[size - 1] = '\0';
 
+int bpf__strerror_prepare_load(const char *filename, bool source,
+                              int err, char *buf, size_t size)
+{
+       size_t n;
+       int ret;
+
+       n = snprintf(buf, size, "Failed to load %s%s: ",
+                        filename, source ? " from source" : "");
+       if (n >= size) {
+               buf[size - 1] = '\0';
+               return 0;
+       }
+       buf += n;
+       size -= n;
+
+       ret = bpf_loader_strerror(err, buf, size);
+       buf[size - 1] = '\0';
+       return ret;
+}
+
 int bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
                        int err, char *buf, size_t size)
 {
        bpf__strerror_head(err, buf, size);
        bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'");
-       bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n");
-       bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n");
+       bpf__strerror_entry(EACCES, "You need to be root");
+       bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0");
+       bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file");
        bpf__strerror_end(buf, size);
        return 0;
 }
 
-int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
+int bpf__strerror_load(struct bpf_object *obj,
                       int err, char *buf, size_t size)
 {
        bpf__strerror_head(err, buf, size);
-       bpf__strerror_entry(EINVAL, "%s: Are you root and runing a CONFIG_BPF_SYSCALL kernel?",
-                           emsg)
+       case LIBBPF_ERRNO__KVER: {
+               unsigned int obj_kver = bpf_object__get_kversion(obj);
+               unsigned int real_kver;
+
+               if (fetch_kernel_version(&real_kver, NULL, 0)) {
+                       scnprintf(buf, size, "Unable to fetch kernel version");
+                       break;
+               }
+
+               if (obj_kver != real_kver) {
+                       scnprintf(buf, size,
+                                 "'version' ("KVER_FMT") doesn't match running kernel ("KVER_FMT")",
+                                 KVER_PARAM(obj_kver),
+                                 KVER_PARAM(real_kver));
+                       break;
+               }
+
+               scnprintf(buf, size, "Failed to load program for unknown reason");
+               break;
+       }
        bpf__strerror_end(buf, size);
        return 0;
 }
index ccd8d7fd79d3443bde634534580883a19adde53e..9caf3ae4acf3d018a87d92bb62f16c4337bd6388 100644 (file)
@@ -8,9 +8,21 @@
 #include <linux/compiler.h>
 #include <linux/err.h>
 #include <string.h>
+#include <bpf/libbpf.h>
 #include "probe-event.h"
 #include "debug.h"
 
+enum bpf_loader_errno {
+       __BPF_LOADER_ERRNO__START = __LIBBPF_ERRNO__START - 100,
+       /* Invalid config string */
+       BPF_LOADER_ERRNO__CONFIG = __BPF_LOADER_ERRNO__START,
+       BPF_LOADER_ERRNO__GROUP,        /* Invalid group name */
+       BPF_LOADER_ERRNO__EVENTNAME,    /* Event name is missing */
+       BPF_LOADER_ERRNO__INTERNAL,     /* BPF loader internal error */
+       BPF_LOADER_ERRNO__COMPILE,      /* Error when compiling BPF scriptlet */
+       __BPF_LOADER_ERRNO__END,
+};
+
 struct bpf_object;
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
@@ -19,6 +31,11 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
 
 #ifdef HAVE_LIBBPF_SUPPORT
 struct bpf_object *bpf__prepare_load(const char *filename, bool source);
+int bpf__strerror_prepare_load(const char *filename, bool source,
+                              int err, char *buf, size_t size);
+
+struct bpf_object *bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz,
+                                           const char *name);
 
 void bpf__clear(void);
 
@@ -41,6 +58,13 @@ bpf__prepare_load(const char *filename __maybe_unused,
        return ERR_PTR(-ENOTSUP);
 }
 
+static inline struct bpf_object *
+bpf__prepare_load_buffer(void *obj_buf __maybe_unused,
+                                          size_t obj_buf_sz __maybe_unused)
+{
+       return ERR_PTR(-ENOTSUP);
+}
+
 static inline void bpf__clear(void) { }
 
 static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;}
@@ -67,6 +91,15 @@ __bpf_strerror(char *buf, size_t size)
        return 0;
 }
 
+static inline
+int bpf__strerror_prepare_load(const char *filename __maybe_unused,
+                              bool source __maybe_unused,
+                              int err __maybe_unused,
+                              char *buf, size_t size)
+{
+       return __bpf_strerror(buf, size);
+}
+
 static inline int
 bpf__strerror_probe(struct bpf_object *obj __maybe_unused,
                    int err __maybe_unused,
index d909459fb54cb2e24ec8da304935fed8424c2026..217b5a60e2ab0e000fbd4ff75445665d08833ba6 100644 (file)
@@ -76,6 +76,7 @@ struct perf_tool build_id__mark_dso_hit_ops = {
        .exit   = perf_event__exit_del_thread,
        .attr            = perf_event__process_attr,
        .build_id        = perf_event__process_build_id,
+       .ordered_events  = true,
 };
 
 int build_id__sprintf(const u8 *build_id, int len, char *bf)
index 7c0c08386a1d9d6fb5e8cba6c838e5c3c1949bd7..425df5c86c9c9acc8a1cb9dd87540f677e885c5e 100644 (file)
@@ -933,6 +933,7 @@ static struct dso *__dso__findlink_by_longname(struct rb_root *root,
                /* Add new node and rebalance tree */
                rb_link_node(&dso->rb_node, parent, p);
                rb_insert_color(&dso->rb_node, root);
+               dso->root = root;
        }
        return NULL;
 }
@@ -945,15 +946,30 @@ static inline struct dso *__dso__find_by_longname(struct rb_root *root,
 
 void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
 {
+       struct rb_root *root = dso->root;
+
        if (name == NULL)
                return;
 
        if (dso->long_name_allocated)
                free((char *)dso->long_name);
 
+       if (root) {
+               rb_erase(&dso->rb_node, root);
+               /*
+                * __dso__findlink_by_longname() isn't guaranteed to add it
+                * back, so a clean removal is required here.
+                */
+               RB_CLEAR_NODE(&dso->rb_node);
+               dso->root = NULL;
+       }
+
        dso->long_name           = name;
        dso->long_name_len       = strlen(name);
        dso->long_name_allocated = name_allocated;
+
+       if (root)
+               __dso__findlink_by_longname(root, dso, NULL);
 }
 
 void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
@@ -1046,6 +1062,7 @@ struct dso *dso__new(const char *name)
                dso->kernel = DSO_TYPE_USER;
                dso->needs_swap = DSO_SWAP__UNSET;
                RB_CLEAR_NODE(&dso->rb_node);
+               dso->root = NULL;
                INIT_LIST_HEAD(&dso->node);
                INIT_LIST_HEAD(&dso->data.open_entry);
                pthread_mutex_init(&dso->lock, NULL);
index fc8db9c764acace9c905d5429d999e9c1401d0c4..45ec4d0a50eda2f8c3b3bc700e573ce89ed58fc8 100644 (file)
@@ -135,6 +135,7 @@ struct dso {
        pthread_mutex_t  lock;
        struct list_head node;
        struct rb_node   rb_node;       /* rbtree node sorted by long name */
+       struct rb_root   *root;         /* root of rbtree that rb_node is in */
        struct rb_root   symbols[MAP__NR_TYPES];
        struct rb_root   symbol_names[MAP__NR_TYPES];
        struct {
index 4f6a4780bd5feebcae44a480599dea6453ed557b..00724d496d38c41483d074b52ff84768441151b3 100644 (file)
@@ -4,17 +4,18 @@
  */
 
 #include <stdio.h>
-#include <sys/utsname.h>
 #include "util.h"
 #include "debug.h"
 #include "llvm-utils.h"
 #include "cache.h"
 
 #define CLANG_BPF_CMD_DEFAULT_TEMPLATE                         \
-               "$CLANG_EXEC -D__KERNEL__ $CLANG_OPTIONS "      \
-               "$KERNEL_INC_OPTIONS -Wno-unused-value "        \
-               "-Wno-pointer-sign -working-directory "         \
-               "$WORKING_DIR -c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
+               "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
+               "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE "     \
+               "$CLANG_OPTIONS $KERNEL_INC_OPTIONS "           \
+               "-Wno-unused-value -Wno-pointer-sign "          \
+               "-working-directory $WORKING_DIR "              \
+               "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
 
 struct llvm_param llvm_param = {
        .clang_path = "clang",
@@ -214,18 +215,19 @@ static int detect_kbuild_dir(char **kbuild_dir)
        const char *suffix_dir = "";
 
        char *autoconf_path;
-       struct utsname utsname;
 
        int err;
 
        if (!test_dir) {
-               err = uname(&utsname);
-               if (err) {
-                       pr_warning("uname failed: %s\n", strerror(errno));
+               /* _UTSNAME_LENGTH is 65 */
+               char release[128];
+
+               err = fetch_kernel_version(NULL, release,
+                                          sizeof(release));
+               if (err)
                        return -EINVAL;
-               }
 
-               test_dir = utsname.release;
+               test_dir = release;
                prefix_dir = "/lib/modules/";
                suffix_dir = "/build";
        }
@@ -326,13 +328,15 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 int llvm__compile_bpf(const char *path, void **p_obj_buf,
                      size_t *p_obj_buf_sz)
 {
-       int err;
-       char clang_path[PATH_MAX];
+       size_t obj_buf_sz;
+       void *obj_buf = NULL;
+       int err, nr_cpus_avail;
+       unsigned int kernel_version;
+       char linux_version_code_str[64];
        const char *clang_opt = llvm_param.clang_opt;
-       const char *template = llvm_param.clang_bpf_cmd_template;
+       char clang_path[PATH_MAX], nr_cpus_avail_str[64];
        char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
-       void *obj_buf = NULL;
-       size_t obj_buf_sz;
+       const char *template = llvm_param.clang_bpf_cmd_template;
 
        if (!template)
                template = CLANG_BPF_CMD_DEFAULT_TEMPLATE;
@@ -354,6 +358,24 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
         */
        get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
 
+       nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+       if (nr_cpus_avail <= 0) {
+               pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"        \tUse 128 instead.\n", strerror(errno));
+               nr_cpus_avail = 128;
+       }
+       snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
+                nr_cpus_avail);
+
+       if (fetch_kernel_version(&kernel_version, NULL, 0))
+               kernel_version = 0;
+
+       snprintf(linux_version_code_str, sizeof(linux_version_code_str),
+                "0x%x", kernel_version);
+
+       force_set_env("NR_CPUS", nr_cpus_avail_str);
+       force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
        force_set_env("CLANG_EXEC", clang_path);
        force_set_env("CLANG_OPTIONS", clang_opt);
        force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
index 5ef90be2a2497a05731a5fb8d24af33a192f2011..8b303ff20289a8ffb4baff9e29292dd47e9068eb 100644 (file)
@@ -91,6 +91,7 @@ static void dsos__purge(struct dsos *dsos)
 
        list_for_each_entry_safe(pos, n, &dsos->head, node) {
                RB_CLEAR_NODE(&pos->rb_node);
+               pos->root = NULL;
                list_del_init(&pos->node);
                dso__put(pos);
        }
index 4e38c396a897ad9599d1addb1fb464b5cdfa4129..afc6b56cf749b687c297018dcae986fef977859c 100644 (file)
@@ -644,6 +644,12 @@ size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
        return printed;
 }
 
+static void __map_groups__insert(struct map_groups *mg, struct map *map)
+{
+       __maps__insert(&mg->maps[map->type], map);
+       map->groups = mg;
+}
+
 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
 {
        struct rb_root *root;
@@ -682,7 +688,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
                        }
 
                        before->end = map->start;
-                       __maps__insert(maps, before);
+                       __map_groups__insert(pos->groups, before);
                        if (verbose >= 2)
                                map__fprintf(before, fp);
                }
@@ -696,7 +702,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
                        }
 
                        after->start = map->end;
-                       __maps__insert(maps, after);
+                       __map_groups__insert(pos->groups, after);
                        if (verbose >= 2)
                                map__fprintf(after, fp);
                }
index bee60583839a7cdae0dd44f5c48dd818d53cb5e4..e48d9da757078f0c35afae590ce87ac7892dafab 100644 (file)
@@ -632,19 +632,20 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
        struct bpf_object *obj;
 
        obj = bpf__prepare_load(bpf_file_name, source);
-       if (IS_ERR(obj) || !obj) {
+       if (IS_ERR(obj)) {
                char errbuf[BUFSIZ];
                int err;
 
-               err = obj ? PTR_ERR(obj) : -EINVAL;
+               err = PTR_ERR(obj);
 
                if (err == -ENOTSUP)
                        snprintf(errbuf, sizeof(errbuf),
                                 "BPF support is not compiled");
                else
-                       snprintf(errbuf, sizeof(errbuf),
-                                "BPF object file '%s' is invalid",
-                                bpf_file_name);
+                       bpf__strerror_prepare_load(bpf_file_name,
+                                                  source,
+                                                  -err, errbuf,
+                                                  sizeof(errbuf));
 
                data->error->help = strdup("(add -v to see detail)");
                data->error->str = strdup(errbuf);
index b51a8bfb40f92cd861d0954ed84e71e15ee50784..03875f9154e7562c060e5935d30bc65d6ba0973b 100644 (file)
@@ -1895,9 +1895,8 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
                sym = map__find_symbol(map, addr, NULL);
        } else {
                if (tp->symbol && !addr) {
-                       ret = kernel_get_symbol_address_by_name(tp->symbol,
-                                                       &addr, true, false);
-                       if (ret < 0)
+                       if (kernel_get_symbol_address_by_name(tp->symbol,
+                                               &addr, true, false) < 0)
                                goto out;
                }
                if (addr) {
@@ -1905,6 +1904,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
                        sym = __find_kernel_function(addr, &map);
                }
        }
+
        if (!sym)
                goto out;
 
index 89dbeb92c68e9de1bc001edddd902940700ab4f2..e3b3b92e44587350b86797e93e57900afd71f94e 100644 (file)
@@ -138,6 +138,9 @@ struct strlist *probe_file__get_rawlist(int fd)
        char *p;
        struct strlist *sl;
 
+       if (fd < 0)
+               return NULL;
+
        sl = strlist__new(NULL, NULL);
 
        fp = fdopen(dup(fd), "r");
@@ -271,6 +274,9 @@ int probe_file__get_events(int fd, struct strfilter *filter,
        const char *p;
        int ret = -ENOENT;
 
+       if (!plist)
+               return -EINVAL;
+
        namelist = __probe_file__get_namelist(fd, true);
        if (!namelist)
                return -ENOENT;
index bd8f03de5e408293a642478a795c6436143edbcf..05012bb178d7a8d75ebf4879438fbc0d6f774926 100644 (file)
@@ -1183,7 +1183,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
                        container_of(pf, struct trace_event_finder, pf);
        struct perf_probe_point *pp = &pf->pev->point;
        struct probe_trace_event *tev;
-       struct perf_probe_arg *args;
+       struct perf_probe_arg *args = NULL;
        int ret, i;
 
        /* Check number of tevs */
@@ -1198,19 +1198,23 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
        ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
                                     pp->retprobe, pp->function, &tev->point);
        if (ret < 0)
-               return ret;
+               goto end;
 
        tev->point.realname = strdup(dwarf_diename(sc_die));
-       if (!tev->point.realname)
-               return -ENOMEM;
+       if (!tev->point.realname) {
+               ret = -ENOMEM;
+               goto end;
+       }
 
        pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
                 tev->point.offset);
 
        /* Expand special probe argument if exist */
        args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
-       if (args == NULL)
-               return -ENOMEM;
+       if (args == NULL) {
+               ret = -ENOMEM;
+               goto end;
+       }
 
        ret = expand_probe_args(sc_die, pf, args);
        if (ret < 0)
@@ -1234,6 +1238,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
        }
 
 end:
+       if (ret) {
+               clear_probe_trace_event(tev);
+               tf->ntevs--;
+       }
        free(args);
        return ret;
 }
@@ -1246,7 +1254,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
        struct trace_event_finder tf = {
                        .pf = {.pev = pev, .callback = add_probe_trace_event},
                        .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
-       int ret;
+       int ret, i;
 
        /* Allocate result tevs array */
        *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
@@ -1258,6 +1266,8 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
 
        ret = debuginfo__find_probes(dbg, &tf.pf);
        if (ret < 0) {
+               for (i = 0; i < tf.ntevs; i++)
+                       clear_probe_trace_event(&tf.tevs[i]);
                zfree(tevs);
                return ret;
        }
index 428149bc64d23c6a12e9c141fb3070809090ad36..c35ffdd360fe13e1590559217365e0f78414e91c 100644 (file)
@@ -29,7 +29,7 @@ static int perf_session__open(struct perf_session *session)
        struct perf_data_file *file = session->file;
 
        if (perf_session__read_header(session) < 0) {
-               pr_err("incompatible file format (rerun with -v to learn more)");
+               pr_err("incompatible file format (rerun with -v to learn more)\n");
                return -1;
        }
 
@@ -37,17 +37,17 @@ static int perf_session__open(struct perf_session *session)
                return 0;
 
        if (!perf_evlist__valid_sample_type(session->evlist)) {
-               pr_err("non matching sample_type");
+               pr_err("non matching sample_type\n");
                return -1;
        }
 
        if (!perf_evlist__valid_sample_id_all(session->evlist)) {
-               pr_err("non matching sample_id_all");
+               pr_err("non matching sample_id_all\n");
                return -1;
        }
 
        if (!perf_evlist__valid_read_format(session->evlist)) {
-               pr_err("non matching read_format");
+               pr_err("non matching read_format\n");
                return -1;
        }
 
index 2a5d8d7698aedb8c82bdf8488f1fb62ded5b438a..6ac03146889d29be60707efd6e04c27c919f64de 100644 (file)
@@ -413,6 +413,11 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
                        ratio = total / avg;
 
                fprintf(out, " # %8.0f cycles / elision       ", ratio);
+       } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) {
+               if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
+                       fprintf(out, " # %8.3f CPUs utilized          ", avg / ratio);
+               else
+                       fprintf(out, "                                   ");
        } else if (runtime_nsecs_stats[cpu].n != 0) {
                char unit = 'M';
 
index b4cc7662677ec858cddf6dd90e906f75c5a14200..cd08027a6d2cdb9640734a5ba8eb20ade14f57f2 100644 (file)
@@ -654,19 +654,24 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
        struct map_groups *kmaps = map__kmaps(map);
        struct map *curr_map;
        struct symbol *pos;
-       int count = 0, moved = 0;
+       int count = 0;
+       struct rb_root old_root = dso->symbols[map->type];
        struct rb_root *root = &dso->symbols[map->type];
        struct rb_node *next = rb_first(root);
 
        if (!kmaps)
                return -1;
 
+       *root = RB_ROOT;
+
        while (next) {
                char *module;
 
                pos = rb_entry(next, struct symbol, rb_node);
                next = rb_next(&pos->rb_node);
 
+               rb_erase_init(&pos->rb_node, &old_root);
+
                module = strchr(pos->name, '\t');
                if (module)
                        *module = '\0';
@@ -674,28 +679,21 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
                curr_map = map_groups__find(kmaps, map->type, pos->start);
 
                if (!curr_map || (filter && filter(curr_map, pos))) {
-                       rb_erase_init(&pos->rb_node, root);
                        symbol__delete(pos);
-               } else {
-                       pos->start -= curr_map->start - curr_map->pgoff;
-                       if (pos->end)
-                               pos->end -= curr_map->start - curr_map->pgoff;
-                       if (curr_map->dso != map->dso) {
-                               rb_erase_init(&pos->rb_node, root);
-                               symbols__insert(
-                                       &curr_map->dso->symbols[curr_map->type],
-                                       pos);
-                               ++moved;
-                       } else {
-                               ++count;
-                       }
+                       continue;
                }
+
+               pos->start -= curr_map->start - curr_map->pgoff;
+               if (pos->end)
+                       pos->end -= curr_map->start - curr_map->pgoff;
+               symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
+               ++count;
        }
 
        /* Symbols have been adjusted */
        dso->adjust_symbols = 1;
 
-       return count + moved;
+       return count;
 }
 
 /*
@@ -1438,9 +1436,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
                if (lstat(dso->name, &st) < 0)
                        goto out;
 
-               if (st.st_uid && (st.st_uid != geteuid())) {
+               if (!symbol_conf.force && st.st_uid && (st.st_uid != geteuid())) {
                        pr_warning("File %s not owned by current user or root, "
-                               "ignoring it.\n", dso->name);
+                                  "ignoring it (use -f to override).\n", dso->name);
                        goto out;
                }
 
index 40073c60b83d6b7e91fe2e3208f50210cf61f6ce..dcd786e364f2da1385c2f78803fe1770071ce609 100644 (file)
@@ -84,6 +84,7 @@ struct symbol_conf {
        unsigned short  priv_size;
        unsigned short  nr_events;
        bool            try_vmlinux_path,
+                       force,
                        ignore_vmlinux,
                        ignore_vmlinux_buildid,
                        show_kernel_path,
index cd12c25e4ea408b1b873d8368f5081d3e2a72113..47b1e36c7ea0c948b0fc9cd247c4a29cf61464a8 100644 (file)
@@ -3,6 +3,7 @@
 #include "debug.h"
 #include <api/fs/fs.h>
 #include <sys/mman.h>
+#include <sys/utsname.h>
 #ifdef HAVE_BACKTRACE_SUPPORT
 #include <execinfo.h>
 #endif
@@ -665,3 +666,32 @@ bool find_process(const char *name)
        closedir(dir);
        return ret ? false : true;
 }
+
+int
+fetch_kernel_version(unsigned int *puint, char *str,
+                    size_t str_size)
+{
+       struct utsname utsname;
+       int version, patchlevel, sublevel, err;
+
+       if (uname(&utsname))
+               return -1;
+
+       if (str && str_size) {
+               strncpy(str, utsname.release, str_size);
+               str[str_size - 1] = '\0';
+       }
+
+       err = sscanf(utsname.release, "%d.%d.%d",
+                    &version, &patchlevel, &sublevel);
+
+       if (err != 3) {
+               pr_debug("Unablt to get kernel version from uname '%s'\n",
+                        utsname.release);
+               return -1;
+       }
+
+       if (puint)
+               *puint = (version << 16) + (patchlevel << 8) + sublevel;
+       return 0;
+}
index 4cfb913aa9e04bffd94286ac426bac4c1221e9c4..dcc659017976da2a90ae67e51b922bcb7bb99a51 100644 (file)
@@ -350,4 +350,12 @@ static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int
 
 int get_stack_size(const char *str, unsigned long *_size);
 
+int fetch_kernel_version(unsigned int *puint,
+                        char *str, size_t str_sz);
+#define KVER_VERSION(x)                (((x) >> 16) & 0xff)
+#define KVER_PATCHLEVEL(x)     (((x) >> 8) & 0xff)
+#define KVER_SUBLEVEL(x)       ((x) & 0xff)
+#define KVER_FMT       "%d.%d.%d"
+#define KVER_PARAM(x)  KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
+
 #endif /* GIT_COMPAT_UTIL_H */
index 8d6a47514253822bb0673968707bc4ecc6a7749e..2c768cf70128cb2d8bbd6a151b6ec51414dafc65 100644 (file)
@@ -134,7 +134,7 @@ void decode_psb(char *p, int numpst)
 }
 
 static struct option info_opts[] = {
-       {.name = "numpst",      .has_arg=no_argument,   .flag=NULL, .val='n'},
+     {"numpst", no_argument, NULL, 'n'},
 };
 
 void print_help(void)
index 3e6799d7a79f1d951f1d6e95f65f337663c8f286..580c4e3ea92ad5425cb0b0c458c2d3fbfa23983c 100644 (file)
@@ -20,7 +20,9 @@ Disable a specific processor sleep state.
 Enable a specific processor sleep state.
 .TP
 \fB\-D\fR \fB\-\-disable-by-latency\fR <LATENCY>
-Disable all idle states with a equal or higher latency than <LATENCY>
+Disable all idle states with a equal or higher latency than <LATENCY>.
+
+Enable all idle states with a latency lower than <LATENCY>.
 .TP
 \fB\-E\fR \fB\-\-enable-all\fR
 Enable all idle states if not enabled already.
index b4b90a97662cda4abe72c82419c815888231235b..0e676433024109bef6d9a87e08709c40be37b2df 100644 (file)
@@ -536,21 +536,21 @@ static int get_latency(unsigned int cpu, unsigned int human)
 }
 
 static struct option info_opts[] = {
-       { .name = "debug",      .has_arg = no_argument,         .flag = NULL,   .val = 'e'},
-       { .name = "boost",      .has_arg = no_argument,         .flag = NULL,   .val = 'b'},
-       { .name = "freq",       .has_arg = no_argument,         .flag = NULL,   .val = 'f'},
-       { .name = "hwfreq",     .has_arg = no_argument,         .flag = NULL,   .val = 'w'},
-       { .name = "hwlimits",   .has_arg = no_argument,         .flag = NULL,   .val = 'l'},
-       { .name = "driver",     .has_arg = no_argument,         .flag = NULL,   .val = 'd'},
-       { .name = "policy",     .has_arg = no_argument,         .flag = NULL,   .val = 'p'},
-       { .name = "governors",  .has_arg = no_argument,         .flag = NULL,   .val = 'g'},
-       { .name = "related-cpus", .has_arg = no_argument,       .flag = NULL,   .val = 'r'},
-       { .name = "affected-cpus",.has_arg = no_argument,       .flag = NULL,   .val = 'a'},
-       { .name = "stats",      .has_arg = no_argument,         .flag = NULL,   .val = 's'},
-       { .name = "latency",    .has_arg = no_argument,         .flag = NULL,   .val = 'y'},
-       { .name = "proc",       .has_arg = no_argument,         .flag = NULL,   .val = 'o'},
-       { .name = "human",      .has_arg = no_argument,         .flag = NULL,   .val = 'm'},
-       { .name = "no-rounding", .has_arg = no_argument,        .flag = NULL,   .val = 'n'},
+       {"debug",        no_argument,            NULL,   'e'},
+       {"boost",        no_argument,            NULL,   'b'},
+       {"freq",         no_argument,            NULL,   'f'},
+       {"hwfreq",       no_argument,            NULL,   'w'},
+       {"hwlimits",     no_argument,            NULL,   'l'},
+       {"driver",       no_argument,            NULL,   'd'},
+       {"policy",       no_argument,            NULL,   'p'},
+       {"governors",    no_argument,            NULL,   'g'},
+       {"related-cpus",  no_argument,   NULL,   'r'},
+       {"affected-cpus", no_argument,   NULL,   'a'},
+       {"stats",        no_argument,            NULL,   's'},
+       {"latency",      no_argument,            NULL,   'y'},
+       {"proc",         no_argument,            NULL,   'o'},
+       {"human",        no_argument,            NULL,   'm'},
+       {"no-rounding", no_argument,     NULL,   'n'},
        { },
 };
 
index 4e213576381eab03c64444b6acee614e9c84f874..0fbd1a22c0a984c0ceac2f832ca791058c0d1524 100644 (file)
 #define NORM_FREQ_LEN 32
 
 static struct option set_opts[] = {
-       { .name = "min",        .has_arg = required_argument,   .flag = NULL,   .val = 'd'},
-       { .name = "max",        .has_arg = required_argument,   .flag = NULL,   .val = 'u'},
-       { .name = "governor",   .has_arg = required_argument,   .flag = NULL,   .val = 'g'},
-       { .name = "freq",       .has_arg = required_argument,   .flag = NULL,   .val = 'f'},
-       { .name = "related",    .has_arg = no_argument,         .flag = NULL,   .val='r'},
+       {"min",         required_argument,      NULL, 'd'},
+       {"max",         required_argument,      NULL, 'u'},
+       {"governor",    required_argument,      NULL, 'g'},
+       {"freq",        required_argument,      NULL, 'f'},
+       {"related",     no_argument,            NULL, 'r'},
        { },
 };
 
index 75e66de7e7a7fc9934ec005667c6857cff42ff04..750c1d82c3f7b7f16a3eea71df3c9d6e7a4ceb7d 100644 (file)
@@ -126,8 +126,8 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
 }
 
 static struct option info_opts[] = {
-       { .name = "silent",     .has_arg = no_argument, .flag = NULL,   .val = 's'},
-       { .name = "proc",       .has_arg = no_argument, .flag = NULL,   .val = 'o'},
+       {"silent", no_argument, NULL, 's'},
+       {"proc", no_argument, NULL, 'o'},
        { },
 };
 
index d45d8d775c021482ab7a4d113351c7f6abd9a9ac..d6b6ae44b8c247ffdb6378d8dcd3cb36f0265142 100644 (file)
 #include "helpers/sysfs.h"
 
 static struct option info_opts[] = {
-       { .name = "disable",
-         .has_arg = required_argument, .flag = NULL,   .val = 'd'},
-       { .name = "enable",
-         .has_arg = required_argument, .flag = NULL,   .val = 'e'},
-       { .name = "disable-by-latency",
-         .has_arg = required_argument, .flag = NULL,   .val = 'D'},
-       { .name = "enable-all",
-         .has_arg = no_argument,       .flag = NULL,   .val = 'E'},
-       { },
+     {"disable",       required_argument,              NULL, 'd'},
+     {"enable",                required_argument,              NULL, 'e'},
+     {"disable-by-latency", required_argument,         NULL, 'D'},
+     {"enable-all",    no_argument,                    NULL, 'E'},
+     { },
 };
 
 
@@ -148,14 +144,21 @@ int cmd_idle_set(int argc, char **argv)
                                        (cpu, idlestate);
                                state_latency = sysfs_get_idlestate_latency
                                        (cpu, idlestate);
-                               printf("CPU: %u - idlestate %u - state_latency: %llu - latency: %llu\n",
-                                      cpu, idlestate, state_latency, latency);
-                               if (disabled == 1 || latency > state_latency)
+                               if (disabled == 1) {
+                                       if (latency > state_latency){
+                                               ret = sysfs_idlestate_disable
+                                                       (cpu, idlestate, 0);
+                                               if (ret == 0)
+               printf(_("Idlestate %u enabled on CPU %u\n"),  idlestate, cpu);
+                                       }
                                        continue;
-                               ret = sysfs_idlestate_disable
-                                       (cpu, idlestate, 1);
-                               if (ret == 0)
+                               }
+                               if (latency <= state_latency){
+                                       ret = sysfs_idlestate_disable
+                                               (cpu, idlestate, 1);
+                                       if (ret == 0)
                printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
+                               }
                        }
                        break;
                case 'E':
index 136d979e958634b83a3f2cd007a7d192036ee152..10299f2e9d2a6917f0601dd07eedb0ff03c6bc92 100644 (file)
@@ -17,8 +17,8 @@
 #include "helpers/sysfs.h"
 
 static struct option set_opts[] = {
-       { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
-       { },
+     {"perf-bias", optional_argument, NULL, 'b'},
+     { },
 };
 
 static void print_wrong_arg_exit(void)
index 573c75f8e3f5da78afdfd4b2e22dff9cde18d01e..3e6f374f8dd73ddc1fd1b6d3b30f175fcc7f9e4b 100644 (file)
@@ -18,7 +18,7 @@
 #include "helpers/bitmask.h"
 
 static struct option set_opts[] = {
-       { .name = "perf-bias",  .has_arg = required_argument,   .flag = NULL,   .val = 'b'},
+       {"perf-bias", required_argument, NULL, 'b'},
        { },
 };
 
index cea398c176e7f29057a24463f296300f8ce5f23f..9cbb7fd7517122c423d316efb5e736a52c799d3a 100644 (file)
@@ -73,18 +73,22 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
        for (cpu = 0; cpu < cpus; cpu++) {
                cpu_top->core_info[cpu].cpu = cpu;
                cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
-               if (!cpu_top->core_info[cpu].is_online)
-                       continue;
                if(sysfs_topology_read_file(
                        cpu,
                        "physical_package_id",
-                       &(cpu_top->core_info[cpu].pkg)) < 0)
-                       return -1;
+                       &(cpu_top->core_info[cpu].pkg)) < 0) {
+                       cpu_top->core_info[cpu].pkg = -1;
+                       cpu_top->core_info[cpu].core = -1;
+                       continue;
+               }
                if(sysfs_topology_read_file(
                        cpu,
                        "core_id",
-                       &(cpu_top->core_info[cpu].core)) < 0)
-                       return -1;
+                       &(cpu_top->core_info[cpu].core)) < 0) {
+                       cpu_top->core_info[cpu].pkg = -1;
+                       cpu_top->core_info[cpu].core = -1;
+                       continue;
+               }
        }
 
        qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
@@ -95,12 +99,15 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
           done by pkg value. */
        last_pkg = cpu_top->core_info[0].pkg;
        for(cpu = 1; cpu < cpus; cpu++) {
-               if(cpu_top->core_info[cpu].pkg != last_pkg) {
+               if (cpu_top->core_info[cpu].pkg != last_pkg &&
+                               cpu_top->core_info[cpu].pkg != -1) {
+
                        last_pkg = cpu_top->core_info[cpu].pkg;
                        cpu_top->pkgs++;
                }
        }
-       cpu_top->pkgs++;
+       if (!cpu_top->core_info[0].pkg == -1)
+               cpu_top->pkgs++;
 
        /* Intel's cores count is not consecutively numbered, there may
         * be a core_id of 3, but none of 2. Assume there always is 0
index c4bae9203a692f2065ee9ec4f8d747c0912d8a94..05f953f0f0a0cf2b3d479ce6a6dcbc9c0d9a8c28 100644 (file)
@@ -143,6 +143,9 @@ void print_results(int topology_depth, int cpu)
        /* Be careful CPUs may got resorted for pkg value do not just use cpu */
        if (!bitmask_isbitset(cpus_chosen, cpu_top.core_info[cpu].cpu))
                return;
+       if (!cpu_top.core_info[cpu].is_online &&
+           cpu_top.core_info[cpu].pkg == -1)
+               return;
 
        if (topology_depth > 2)
                printf("%4d|", cpu_top.core_info[cpu].pkg);
@@ -191,7 +194,8 @@ void print_results(int topology_depth, int cpu)
         * It's up to the monitor plug-in to check .is_online, this one
         * is just for additional info.
         */
-       if (!cpu_top.core_info[cpu].is_online) {
+       if (!cpu_top.core_info[cpu].is_online &&
+           cpu_top.core_info[cpu].pkg != -1) {
                printf(_(" *is offline\n"));
                return;
        } else
@@ -388,6 +392,9 @@ int cmd_monitor(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
+       if (!cpu_top.core_info[0].is_online)
+               printf("WARNING: at least one cpu is offline\n");
+
        /* Default is: monitor all CPUs */
        if (bitmask_isallclear(cpus_chosen))
                bitmask_setall(cpus_chosen);
index bde0ef1a63df4876d5149c85f4083eb92561dbb4..0dac7e05a6ac9e5f1500eca1cebbce2d900ab511 100644 (file)
@@ -75,6 +75,7 @@ unsigned int aperf_mperf_multiplier = 1;
 int do_smi;
 double bclk;
 double base_hz;
+unsigned int has_base_hz;
 double tsc_tweak = 1.0;
 unsigned int show_pkg;
 unsigned int show_core;
@@ -96,6 +97,7 @@ unsigned int do_ring_perf_limit_reasons;
 unsigned int crystal_hz;
 unsigned long long tsc_hz;
 int base_cpu;
+double discover_bclk(unsigned int family, unsigned int model);
 
 #define RAPL_PKG               (1 << 0)
                                        /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -511,9 +513,13 @@ int format_counters(struct thread_data *t, struct core_data *c,
        }
 
        /* Bzy_MHz */
-       if (has_aperf)
-               outp += sprintf(outp, "%8.0f",
-                       1.0 * t->tsc * tsc_tweak / units * t->aperf / t->mperf / interval_float);
+       if (has_aperf) {
+               if (has_base_hz)
+                       outp += sprintf(outp, "%8.0f", base_hz / units * t->aperf / t->mperf);
+               else
+                       outp += sprintf(outp, "%8.0f",
+                               1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
+       }
 
        /* TSC_MHz */
        outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
@@ -1158,12 +1164,6 @@ int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV,
 static void
 calculate_tsc_tweak()
 {
-       unsigned long long msr;
-       unsigned int base_ratio;
-
-       get_msr(base_cpu, MSR_NHM_PLATFORM_INFO, &msr);
-       base_ratio = (msr >> 8) & 0xFF;
-       base_hz = base_ratio * bclk * 1000000;
        tsc_tweak = base_hz / tsc_hz;
 }
 
@@ -1173,9 +1173,9 @@ dump_nhm_platform_info(void)
        unsigned long long msr;
        unsigned int ratio;
 
-       get_msr(base_cpu, MSR_NHM_PLATFORM_INFO, &msr);
+       get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_NHM_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
+       fprintf(stderr, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
 
        ratio = (msr >> 40) & 0xFF;
        fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency frequency\n",
@@ -1440,7 +1440,7 @@ dump_config_tdp(void)
        
        get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
        fprintf(stderr, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
-       fprintf(stderr, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xEF);
+       fprintf(stderr, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0x7F);
        fprintf(stderr, " lock=%d", (unsigned int)(msr >> 31) & 1);
        fprintf(stderr, ")\n");
 }
@@ -1807,7 +1807,7 @@ void check_permissions()
  *
  * MSR_SMI_COUNT                   0x00000034
  *
- * MSR_NHM_PLATFORM_INFO           0x000000ce
+ * MSR_PLATFORM_INFO               0x000000ce
  * MSR_NHM_SNB_PKG_CST_CFG_CTL     0x000000e2
  *
  * MSR_PKG_C3_RESIDENCY            0x000003f8
@@ -1821,6 +1821,7 @@ void check_permissions()
 int probe_nhm_msrs(unsigned int family, unsigned int model)
 {
        unsigned long long msr;
+       unsigned int base_ratio;
        int *pkg_cstate_limits;
 
        if (!genuine_intel)
@@ -1829,6 +1830,8 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
        if (family != 6)
                return 0;
 
+       bclk = discover_bclk(family, model);
+
        switch (model) {
        case 0x1A:      /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
        case 0x1E:      /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
@@ -1871,9 +1874,13 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
                return 0;
        }
        get_msr(base_cpu, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
-
        pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
 
+       get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
+       base_ratio = (msr >> 8) & 0xFF;
+
+       base_hz = base_ratio * bclk * 1000000;
+       has_base_hz = 1;
        return 1;
 }
 int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
@@ -2780,7 +2787,6 @@ void process_cpuid()
        do_skl_residency = has_skl_msrs(family, model);
        do_slm_cstates = is_slm(family, model);
        do_knl_cstates  = is_knl(family, model);
-       bclk = discover_bclk(family, model);
 
        rapl_probe(family, model);
        perf_limit_reasons_probe(family, model);
index dce346aa94eabbd3544189af7e3de528da960cb6..40ab4476c80a2039ab543cc94b09725789b2fe57 100644 (file)
@@ -1135,7 +1135,7 @@ static void nfit_test1_setup(struct nfit_test *t)
        memdev->interleave_ways = 1;
        memdev->flags = ACPI_NFIT_MEM_SAVE_FAILED | ACPI_NFIT_MEM_RESTORE_FAILED
                | ACPI_NFIT_MEM_FLUSH_FAILED | ACPI_NFIT_MEM_HEALTH_OBSERVED
-               | ACPI_NFIT_MEM_ARMED;
+               | ACPI_NFIT_MEM_NOT_ARMED;
 
        offset += sizeof(*memdev);
        /* dcr-descriptor0 */
index 3224a049b196e87fd9fe23e0f20ea09c6ea04031..0558bb9ce0a6eadb92aba3a4880aadfa277e0d2c 100644 (file)
@@ -27,7 +27,7 @@ o The build system shall remain as simple as possible, avoiding any archive or
 o Where possible, any helper functions or other package-wide code shall be
   implemented in header files, avoiding the need to compile intermediate object
   files.
-o External dependendencies shall remain as minimal as possible. Currently gcc
+o External dependencies shall remain as minimal as possible. Currently gcc
   and glibc are the only dependencies.
 o Tests return 0 for success and < 0 for failure.
 
index e38cc54942dbf298dd1b880e3eabf5a9f2af29e6..882fe83a355442930a5fc1007a294eee6744b7cc 100644 (file)
@@ -492,6 +492,9 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
        pid_t parent = getppid();
        int fd;
        void *map1, *map2;
+       int page_size = sysconf(_SC_PAGESIZE);
+
+       ASSERT_LT(0, page_size);
 
        ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
        ASSERT_EQ(0, ret);
@@ -504,16 +507,16 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
 
        EXPECT_EQ(parent, syscall(__NR_getppid));
        map1 = (void *)syscall(sysno,
-               NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, PAGE_SIZE);
+               NULL, page_size, PROT_READ, MAP_PRIVATE, fd, page_size);
        EXPECT_NE(MAP_FAILED, map1);
        /* mmap2() should never return. */
        map2 = (void *)syscall(sysno,
-                NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
+                NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0x0C0FFEE);
        EXPECT_EQ(MAP_FAILED, map2);
 
        /* The test failed, so clean up the resources. */
-       munmap(map1, PAGE_SIZE);
-       munmap(map2, PAGE_SIZE);
+       munmap(map1, page_size);
+       munmap(map2, page_size);
        close(fd);
 }
 
index bcf5ec760eb9287f5a0b5f99e95518eaed78f6a0..5a6016224bb9c9c4bbe5f7b28c37738f0edec5a3 100644 (file)
@@ -128,6 +128,7 @@ static const char * const page_flag_names[] = {
        [KPF_THP]               = "t:thp",
        [KPF_BALLOON]           = "o:balloon",
        [KPF_ZERO_PAGE]         = "z:zero_page",
+       [KPF_IDLE]              = "i:idle_page",
 
        [KPF_RESERVED]          = "r:reserved",
        [KPF_MLOCKED]           = "m:mlocked",
index 21a0ab2d891949768d25ff45796f189bad0881e5..69bca185c471d1dec971f02403ae9fd60851f5bd 100644 (file)
@@ -221,17 +221,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
        kvm_timer_update_state(vcpu);
 
        /*
-        * If we enter the guest with the virtual input level to the VGIC
-        * asserted, then we have already told the VGIC what we need to, and
-        * we don't need to exit from the guest until the guest deactivates
-        * the already injected interrupt, so therefore we should set the
-        * hardware active state to prevent unnecessary exits from the guest.
-        *
-        * Conversely, if the virtual input level is deasserted, then always
-        * clear the hardware active state to ensure that hardware interrupts
-        * from the timer triggers a guest exit.
-        */
-       if (timer->irq.level)
+       * If we enter the guest with the virtual input level to the VGIC
+       * asserted, then we have already told the VGIC what we need to, and
+       * we don't need to exit from the guest until the guest deactivates
+       * the already injected interrupt, so therefore we should set the
+       * hardware active state to prevent unnecessary exits from the guest.
+       *
+       * Also, if we enter the guest with the virtual timer interrupt active,
+       * then it must be active on the physical distributor, because we set
+       * the HW bit and the guest must be able to deactivate the virtual and
+       * physical interrupt at the same time.
+       *
+       * Conversely, if the virtual input level is deasserted and the virtual
+       * interrupt is not active, then always clear the hardware active state
+       * to ensure that hardware interrupts from the timer triggers a guest
+       * exit.
+       */
+       if (timer->irq.level || kvm_vgic_map_is_active(vcpu, timer->map))
                phys_active = true;
        else
                phys_active = false;
index 533538385d5d294ce16bae446cc7e2b1578d9b7d..65461f821a75a7ffd3d0bdab471052e7061c8824 100644 (file)
@@ -1096,6 +1096,27 @@ static void vgic_retire_lr(int lr_nr, struct kvm_vcpu *vcpu)
        vgic_set_lr(vcpu, lr_nr, vlr);
 }
 
+static bool dist_active_irq(struct kvm_vcpu *vcpu)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
+}
+
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
+{
+       int i;
+
+       for (i = 0; i < vcpu->arch.vgic_cpu.nr_lr; i++) {
+               struct vgic_lr vlr = vgic_get_lr(vcpu, i);
+
+               if (vlr.irq == map->virt_irq && vlr.state & LR_STATE_ACTIVE)
+                       return true;
+       }
+
+       return dist_active_irq(vcpu);
+}
+
 /*
  * An interrupt may have been disabled after being made pending on the
  * CPU interface (the classic case is a timer running while we're
@@ -1248,7 +1269,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
         * may have been serviced from another vcpu. In all cases,
         * move along.
         */
-       if (!kvm_vgic_vcpu_pending_irq(vcpu) && !kvm_vgic_vcpu_active_irq(vcpu))
+       if (!kvm_vgic_vcpu_pending_irq(vcpu) && !dist_active_irq(vcpu))
                goto epilog;
 
        /* SGIs */
@@ -1396,25 +1417,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 static bool vgic_sync_hwirq(struct kvm_vcpu *vcpu, int lr, struct vgic_lr vlr)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-       struct irq_phys_map *map;
-       bool phys_active;
        bool level_pending;
-       int ret;
 
        if (!(vlr.state & LR_HW))
                return false;
 
-       map = vgic_irq_map_search(vcpu, vlr.irq);
-       BUG_ON(!map);
-
-       ret = irq_get_irqchip_state(map->irq,
-                                   IRQCHIP_STATE_ACTIVE,
-                                   &phys_active);
-
-       WARN_ON(ret);
-
-       if (phys_active)
-               return 0;
+       if (vlr.state & LR_STATE_ACTIVE)
+               return false;
 
        spin_lock(&dist->lock);
        level_pending = process_queued_irq(vcpu, lr, vlr);
@@ -1479,17 +1488,6 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
        return test_bit(vcpu->vcpu_id, dist->irq_pending_on_cpu);
 }
 
-int kvm_vgic_vcpu_active_irq(struct kvm_vcpu *vcpu)
-{
-       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-
-       if (!irqchip_in_kernel(vcpu->kvm))
-               return 0;
-
-       return test_bit(vcpu->vcpu_id, dist->irq_active_on_cpu);
-}
-
-
 void vgic_kick_vcpus(struct kvm *kvm)
 {
        struct kvm_vcpu *vcpu;